Conclusion: recursion and recursion improve efficiency, and other questions are better. This chapter solves my previous doubts about the tower of Hanoi and improves my understanding of the binary representation state, but the last question, the city of fractal, is still a little vague, and I often look back in the follow-up study.
recursion
>Recursive implementation of exponential enumeration
dfs is written in two ways for each person: choose or not. When you make a choice at n intersections, the result will be output.
#include<iostream> using namespace std; int n; void dfs(int u,int state) { if(u == n) { for(int i = 0;i < n;i++) if(state>>i & 1) cout<<i + 1<<' '; puts(""); return ; } //Not selected dfs(u + 1,state); //choose dfs(u + 1,state | 1 << u); } int main() { cin>>n; dfs(0,0); return 0; }
Violence writing is to enumerate all States and output schemes.
#include<iostream> using namespace std; int main() { int n; cin>>n; for(int i = 0;i < (1 << n) ;i++) { for(int j = 0;j < 15;j++) { if(i >> j & 1) cout<<j + 1<<' '; } puts(""); } return 0; }
>Recursive implementation of combinatorial enumeration
Similar to exponential enumeration, the addition of one dimension indicates that several parameters are currently selected. For each bit, select or deselect two branches. When m branches have been selected, the output scheme is.
#include<iostream> using namespace std; int n,m; void dfs(int u,int cnt,int state) { if(cnt == m) { for(int i = 0;i < n;i++) if(state>>i & 1) cout<<i + 1<<' '; puts(""); return ; } if(u == n) return ; //choose dfs(u + 1,cnt + 1,state | 1 << u); //Not selected dfs(u + 1,cnt,state); } int main() { cin>>n>>m; dfs(0,0,0); return 0; }
>Recursive implementation of permutation enumeration
Typical dfs, fill in the number in turn, and use it only if it has not been used before. Traverse the unused in turn, and output it when it is full. Note to restore the state (backtracking)
#include<bits/stdc++.h> using namespace std ; vector<int> path; int n; void dfs(int u,int state) { if(u == n) { for(int i = 0;i < n;i++) cout<<path[i]<<' '; puts(""); return ; } for(int i = 0;i < n;i++) { if(!(state>>i & 1)) { path.push_back(i + 1); dfs(u + 1,state | (1 << i)); path.pop_back(); } } } int main() { cin>>n; dfs(0,0); return 0; }
>Sum of divisors
The sum of the sequence of equal ratios can be obtained in the time of \ (log(c) \) by dividing and treating with the fast power
#include<iostream> using namespace std; const int mod = 9901; int qmi(int a,int b)//Counting { a %= mod; int res = 1; while(b) { if(b&1) res = res * a % mod; a = a * a % mod; b >>= 1; } return res; } int sum(int p,int c)//Divide and conquer sum { if(c == 0) return 1; if(c & 1) return (1 + qmi(p,(c + 1 )/ 2)) % mod * sum(p,(c - 1) / 2) % mod; return ((1 + qmi(p,c / 2)) % mod * sum(p,(c / 2) - 1) + qmi(p,c)) % mod; } int main() { int a,b; cin>>a>>b; int res = 1; for(int i = 2;i <= a;i++) { int s = 0; while(a % i == 0) { s++; a /= i; } if(s) res = res * sum(i,s * b) % mod; } if(!a) res = 0; cout<<res<<endl; return 0; }
This question is a little vague
>Fractal City
Find the corresponding coordinates according to the given level and number, and then carry out coordinate transformation according to level 1 in the topic. High quality problem solution
#include<algorithm> #include<cmath> #include<iostream> using namespace std; typedef long long LL; typedef pair<LL,LL> PLL; PLL cacl(LL n,LL m) { /* n:Grade m: number */ if(n == 0) return {0,0}; LL len = 1ll << (n - 1);//Quadrant side length LL cnt = 1ll << (2 * n - 2);//Capacity in class n - 1 PLL pos = cacl(n-1,m % cnt); LL x = pos.first,y = pos.second; int z = m / cnt;//In which quadrant if(z == 0) return {-y - len,-x + len}; else if(z == 1) return {x + len,y + len}; else if(z == 2) return {x + len,y - len}; return {y - len,x - len}; } int main() { int T; cin>>T; while(T--) { LL N,A,B; cin>>N>>A>>B; auto ac = cacl(N,A-1); auto bc = cacl(N,B-1); double x = ac.first - bc.first, y = ac.second - bc.second; printf("%.0lf\n",sqrt(x * x + y * y) * 5); } return 0; }
Recurrence
>Puzzling switch
Enumerate all the statuses (\ (2 ^ 5 \) of the first row according to which, so that the first row has been determined after pressing. For example: after the status is determined, the first line is 0, which can only be changed to 1 by pressing the second line, which can be pushed down in turn. If the last line is 1, it indicates that it is a legal scheme and counts the minimum number of operations.
#include<iostream> #include<cstring> using namespace std; const int INF = 100000; char g[10][10]; int dx[] = {0,-1,0,1,0}, dy[] = {0,0,1,0,-1}; void turn(int x,int y)//Offset to change the state up, down, left and right { for(int i = 0;i < 5;i++) { int a = x + dx[i], b = y + dy[i]; if(a >= 0 && a < 5 && b >= 0 && b < 5) { g[a][b] = '0' + !(g[a][b] - '0'); } } } int work() { int ans = INF; for(int k = 0;k < 1 << 5;k++)//Enumerate which light to press in the first row { int res = 0; char backup[10][10]; memcpy(backup,g,sizeof g); for(int i = 0;i < 5;i++) { if(k >> i & 1) { res++; turn(0,i); } } for(int i = 0;i < 4;i++) for(int j = 0;j < 5;j++) { if(g[i][j] == '0') { res++; turn(i + 1,j); } } bool is_successful = true; for(int j = 0;j < 5;j++)//See if the last line is all 1 if(g[4][j] == '0') { is_successful = false; break; } if(is_successful) ans = min(ans,res); memcpy(g,backup,sizeof g);//Restore array } if(ans > 6) return -1; return ans; } int main() { int T; cin>>T; while(T--) { for(int i = 0;i < 5;i++) cin>>g[i]; cout<<work()<<endl; } return 0; }
>Strange tower of Hanoi
In the case of four columns, move J to column b. After that, it can only be placed on the remaining three columns, so that the problem will be transformed into the most basic Hanoi Tower problem. Put the rest on column D, and then put that j on column d to complete a scheme.
The most basic Hanoi Tower problem is to put n-1 discs on b first, then put the last disc on c, and then put n-1 discs on c. The recurrence formula is: f[n] = f[n-1] + 1 + f[n-1]
#include<iostream> #include<cstring> using namespace std; int d[13],f[13]; int main() { d[1] = 1; for(int i = 2;i <= 12 ;i++) d[i] = 1 + d[i-1] * 2;//Number of schemes of pretreatment three column mode memset(f,0x3f,sizeof f); f[1] = 1; for(int i = 1;i <= 12;i++) for(int j = 0;j < i;j++) f[i] = min(f[i],f[j] * 2 + d[i - j]);//In four column mode, first move j to b column, then move the rest to the target column in three column mode, and then move j to the target column for(int i = 1;i <= 12;i++) cout<<f[i]<<endl; return 0; }
Hanoi tower with three columns
//Hanoi Tower scheme #include<iostream> using namespace std; int hanoi(int step) { if(step == 1) return 1; return hanoi(step - 1) * 2 + 1; } int main() { int n; cin>>n; cout<<hanoi(n)<<endl; return 0; } //Hanoi Tower implementation #include<iostream> using namespace std; void hanoi(int n,char a,char b,char c) { if(n == 1) { printf("%c -> %c\n",a,c); return ; }else { //Move from column a to column b hanoi(n-1,a,c,b); //After moving n-1, move the largest one to column c printf("%c -> %c\n",a,c); //Move the n-1 stack to column c hanoi(n-1,b,a,c); } }