給一個連加計算式,只包含數字 一、二、3,要求從新排序,使得連加的數字從小到大node
把全部的數字記錄下來,從小到大排序輸出便可ios
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 8 const int N=100005; 9 10 char buff[1000]; 11 int A[1000], n; 12 13 int main() { 14 scanf("%s", buff); 15 n=0; 16 for(int i=0; buff[i]; i+=2) A[n++]=buff[i]-'0'; 17 sort(A, A+n); 18 printf("%d", A[0]); 19 for(int i=1; i<n; i++) printf("+%d", A[i]); 20 printf("\n"); 21 return 0; 22 }
昨晚眼睛盯着屏幕仔仔細細的看了四遍題意,硬是沒看懂...下面是我猜的題意,不知道對不對,反正按照這個題意寫的代碼過了數組
有 n 個房子編號 1 到 n 按照順時針圍成一個圈,相鄰兩個房子之間的距離是 1,有 m 個任務編號 1 到 m,每一個任務爲 i 爲到達相應的房子中去,問順序的(從 1 號任務開始完成到 m 號任務)完成這些任務最少須要走多短的路程ide
模擬題,直接模擬就行函數
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 8 typedef long long LL; 9 const int N=100005; 10 11 int n, m; 12 LL A[N]; 13 14 int main() { 15 scanf("%d%d", &n, &m); 16 for(int i=1; i<=m; i++) { 17 scanf("%I64d", &A[i]); 18 A[i]--; 19 } 20 LL last=0, ans=0; 21 for(int i=1; i<=m; i++) { 22 if(A[i]>=last) ans+=A[i]-last, last=A[i]; 23 else ans+=n-last+A[i], last=A[i]; 24 } 25 printf("%I64d\n", ans); 26 return 0; 27 }
有 10 個重量分別爲 1 到 10 的砝碼可用,以及一個天平,如今往天平上添加砝碼,添加的規則以下:ui
1. 第 i 次添加到左邊的盤中,那麼第 i+1 添加到右邊的盤中spa
2. 第 i 次添加的砝碼的重量不等於第 i+1 次添加的砝碼的重量3d
3. 往一個盤中添加完砝碼以後,要求這個盤中的全部砝碼的重量嚴格大於另外一個盤中砝碼的重量code
給你一些可用的砝碼,以及添加砝碼的次數 m(1 ≤ m ≤ 1000),問是否存在這樣一個砝碼添加序列,存在子的話輸出這個序列blog
動態規劃,定義狀態:f[i][cur][mor] 表示第 i 次添加的砝碼重量是 cur,添加完以後當前盤比另外一盤重 mor 的狀態是否可達,因爲 m 最大爲 1000,砝碼重量最大爲 10,因此狀態的數量爲 10^5,狀態的轉移爲 10,時間複雜度爲 10^6
初值:f[0][i][i]=1 表示第 0 次添加劇量爲 i 的砝碼,添加完以後確定比另外一個空盤多 i,其餘狀態爲 0
轉移:f[i][cur][mor] 能夠推出 f[i+1][nxt][nxt-mor],這裏要求 cur!=nxt 且 nxt-mor>0
終值:f[m-1][i][j] 只要有一個狀態可達,序列存在,往回遞歸的找解,不然不存在
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int N=2006; 8 9 bool f[N][11][11]; 10 char buff[111]; 11 int n; 12 13 void PRINT(int dep, int cho, int mor) { 14 int pre=-1; 15 for(int i=1; i<=10 && pre==-1; i++) 16 if(f[dep-1][i][cho-mor] && i!=cho) pre=i; 17 if(dep==1) printf("%d", pre); 18 else PRINT(dep-1, pre, cho-mor); 19 printf(" %d", cho); 20 } 21 22 int main() { 23 scanf("%s%d", buff, &n); 24 memset(f, 0, sizeof f); 25 for(int i=1; i<=10; i++) if(buff[i-1]=='1') f[0][i][i]=1; 26 for(int i=0; i<n; i++) { 27 for(int j=1; j<=10; j++) { 28 for(int k=1; k<=10; k++) { 29 if(!f[i][j][k]) continue; 30 for(int nxt=1; nxt<=10; nxt++) { 31 if(buff[nxt-1]!='1') continue; 32 if(nxt-k<=0) continue; 33 if(nxt==j) continue; 34 f[i+1][nxt][nxt-k]=1; 35 } 36 } 37 } 38 } 39 int id1=-1, id2=-1; 40 for(int i=1; i<=10 && id1==-1; i++) 41 for(int j=1; j<=10 && id1==-1; j++) { 42 if(f[n-1][i][j]) { 43 id1=i, id2=j; 44 break; 45 } 46 } 47 if(id1==-1) { 48 printf("NO\n"); 49 return 0; 50 } 51 printf("YES\n"); 52 if(n==1) printf("%d\n", id1); 53 else PRINT(n-1, id1, id2), printf("\n"); 54 return 0; 55 }
給一個長度爲 2^n 的數組,如今有 n 個操做,把這個數組變成一個數:
1. 若是 i%2==1 那麼,把第 1 個和第 2 個按位取或獲得新數,把第 3 個和第 4 個按位取或獲得新數...
2. 若是 i%2==0 那麼,把第 1 個和第 2 個按位異或獲得新數,把第 3 個和第 4 個按位異或獲得新數...
如今給了 m 個詢問,每一個詢問先把第 p 個位置的值改成 q,而後輸出按照上面操做獲得的數
數據規模:1 ≤ n ≤ 17, 1 ≤ m ≤ 105
典型的線段樹水題,每一個節點保存以下信息
1. s t 這個節點表示的區間
2. val 這個節點表示的區間按照要求的操做所獲得的數
3. dep 這個節點的層號
每次 pushup 的時候根據層號 pushup:
1. 層號爲奇數 fa.val=L.val 按位或 R.val
2. 層號爲偶數 fa.val=L.val 按位異或 R.val
線段樹有 3 個函數:
1. build 建樹
2. update 將某個位置的值修改
3. pushup 由兒子節點的 val 計算父親節點的 val
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int N=200006; 8 9 int n, m, A[N]; 10 11 struct Segment_Tree { 12 struct Node { 13 int s, t, dep, val; 14 void init(int L, int R, int a) { 15 s=L, t=R, dep=a, val=A[L]; 16 } 17 } T[N<<2]; 18 19 void pushUp(Node &fa, Node &L, Node &R) { 20 if(fa.dep&1) fa.val=L.val|R.val; 21 else fa.val=L.val^R.val; 22 } 23 24 void build(int id, int dep, int L, int R) { 25 T[id].init(L, R, dep); 26 if(L==R) return; 27 int mid=(L+R)>>1; 28 build(id<<1, dep-1, L, mid); 29 build(id<<1|1, dep-1, mid+1, R); 30 pushUp(T[id], T[id<<1], T[id<<1|1]); 31 } 32 33 void update(int id, int pos, int val) { 34 if(T[id].s==T[id].t) { 35 T[id].val=val; 36 return; 37 } 38 int mid=(T[id].s+T[id].t)>>1; 39 if(pos<=mid) update(id<<1, pos, val); 40 else update(id<<1|1, pos, val); 41 pushUp(T[id], T[id<<1], T[id<<1|1]); 42 } 43 } tree; 44 45 int main() { 46 // freopen("in", "r", stdin); 47 scanf("%d%d", &n, &m); 48 int old=n; 49 n=(1<<n); 50 for(int i=1; i<=n; i++) scanf("%d", &A[i]); 51 tree.build(1, old, 1, n); 52 for(int i=0, p, q; i<m; i++) { 53 scanf("%d%d", &p, &q); 54 tree.update(1, p, q); 55 printf("%d\n", tree.T[1].val); 56 } 57 return 0; 58 }
給一個序列,初始時爲:一、二、三、四、...、n
如今每次操做翻轉一個區間的全部數,最多翻轉三次,會獲得一個新的序列
如今給你新的那個序列,要求你給出一個合法的翻轉操做指令,使得從最初的序列變成給你的序列
題目保證存在解,且最多不超過 3 次翻轉
考慮從當前的序列翻回去
假設 [1, L-1], [R+1, n] 這兩個區間是排好序的,即:A[i]=i,對於 i 屬於這兩個區間
[L, R] 這個區間是亂序的,即 A[L]!=L 且 A[R]!=R
另 A[Lpos]=L,A[Rpos]=R
那麼,每次翻轉的時候,有兩種選擇:
1. 翻轉 [L, Lpos]
2. 翻轉 [Rpos, R]
這樣作必然可以將序列翻轉回去,直接 DFS 便可,最後輸出解的時候須要注意:人家問的是怎麼翻轉到當前的序列哦,好多人的答案反了...
當時猜了個結論就寫了,早上醒來想了想證實,挺麻煩的,懶得寫了,好餓啊...
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 8 const int N=10005; 9 10 struct node { 11 int s, t; 12 void init(int a, int b) { 13 s=a, t=b; 14 } 15 } ans[10]; 16 int A[10][N], n; 17 18 int checkL(int dep) { 19 if(A[dep][1]!=1) return 1; 20 for(int i=2; i<=n; i++) if(A[dep][i]!=A[dep][i-1]+1) return i; 21 return -1; 22 } 23 24 int checkR(int dep) { 25 if(A[dep][n]!=n) return n; 26 for(int i=n-1; i>=1; i--) if(A[dep][i]!=A[dep][i+1]-1) return i; 27 return -1; 28 } 29 30 int findpos(int dep, int val) { 31 for(int i=1; i<=n; i++) if(A[dep][i]==val) return i; 32 } 33 34 bool DFS(int dep) { 35 if(dep==3) if(checkL(dep)!=-1) return false; 36 else { 37 printf("%d\n", dep); 38 for(int i=dep-1; i>=0; i--) printf("%d %d\n", ans[i].s, ans[i].t); 39 return true; 40 } 41 42 int L=checkL(dep), R=checkR(dep); 43 if(L==-1 || R==-1) { 44 printf("%d\n", dep); 45 for(int i=dep-1; i>=0; i--) printf("%d %d\n", ans[i].s, ans[i].t); 46 return true; 47 } 48 for(int i=1; i<=n; i++) A[dep+1][i]=A[dep][i]; 49 int Lpos=findpos(dep+1, L), Rpos=findpos(dep+1, R); 50 51 reverse(A[dep+1]+L, A[dep+1]+Lpos+1); 52 ans[dep].init(L, Lpos); 53 if(DFS(dep+1)) return true; 54 reverse(A[dep+1]+L, A[dep+1]+Lpos+1); 55 56 ans[dep].init(Rpos, R); 57 reverse(A[dep+1]+Rpos, A[dep+1]+R+1); 58 if(DFS(dep+1)) return true; 59 reverse(A[dep+1]+Rpos, A[dep+1]+R+1); 60 61 return false; 62 } 63 64 int main() { 65 scanf("%d", &n); 66 for(int i=1; i<=n; i++) scanf("%d", &A[0][i]); 67 DFS(0); 68 return 0; 69 }
這場比賽總算圓了我 div2 AK 一場的夢,爽,不過,題目的質量確實不怎麼樣...