第七届蓝桥杯 前言 (不会吧不会吧不会吧,不会真有大学生到快到四月都没开学吧) 乌丸千岁(💊千岁)
网友年龄 直接循环嵌套穷举就好了,没啥好说的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <bits/stdc++.h> using namespace std;int main () { int ans = 0 ; for (int i = 0 ; i <= 9 ; i++) for (int j = 0 ; j <= 9 ; j++) { if (((i * 10 + j) - (j * 10 + i)) == 27 ) ans++; } cout << ans; return 0 ; }
生日蜡烛 没什么好办法,从0开始枚举开始过生日的可能情况,依次判断就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <bits/stdc++.h> using namespace std;int judge (int x) { int sum = 236 ; int cnt = 0 ; int year = x; while (sum) { if (sum < 0 ) return 0 ; sum -= year; year--; } return year + 1 ; } int main () { for (int i = 20 ; i < 100 ; i++) { if (judge (i)) cout << judge (i); } return 0 ; }
方格填数 对角也算相邻!!!dfs模板题,正常思路是先在之前的递归中将数字填入,最后在最后一次循环进行判断即可。 我当时做麻烦了,以边的形式存图,其实用连接矩阵更好一点。 不过用边存图的话dfs好写一点 总之各有千秋吧,能做出来就行 我的思路大体是,在dfs中间枚举可能情况,边搜边判断,如果有不符合的情况直接筛掉,到最后能构造完的就是正解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <bits/stdc++.h> using namespace std;#define INF 0x3f3f3f3f int ans;bool visit[10 ];int pos[10 ];vector<int > edge[10 ]; void start () { edge[0 ].push_back (1 ), edge[0 ].push_back (4 ), edge[0 ].push_back (3 ), edge[0 ].push_back (5 ); edge[1 ].push_back (0 ), edge[1 ].push_back (5 ), edge[1 ].push_back (2 ), edge[1 ].push_back (4 ), edge[1 ].push_back (6 ); edge[2 ].push_back (1 ), edge[2 ].push_back (6 ), edge[2 ].push_back (5 ); edge[3 ].push_back (4 ), edge[3 ].push_back (7 ), edge[3 ].push_back (8 ), edge[3 ].push_back (0 ); edge[4 ].push_back (3 ), edge[4 ].push_back (8 ), edge[4 ].push_back (5 ), edge[4 ].push_back (0 ), edge[4 ].push_back (9 ), edge[4 ].push_back (7 ), edge[4 ].push_back (1 ); edge[5 ].push_back (1 ), edge[5 ].push_back (4 ), edge[5 ].push_back (9 ), edge[5 ].push_back (6 ), edge[5 ].push_back (0 ), edge[5 ].push_back (2 ), edge[5 ].push_back (8 ); edge[6 ].push_back (2 ), edge[6 ].push_back (5 ), edge[6 ].push_back (1 ), edge[6 ].push_back (9 ); edge[7 ].push_back (3 ), edge[7 ].push_back (8 ), edge[7 ].push_back (4 ); edge[8 ].push_back (7 ), edge[8 ].push_back (4 ), edge[8 ].push_back (9 ), edge[8 ].push_back (3 ), edge[8 ].push_back (5 ); edge[9 ].push_back (8 ), edge[9 ].push_back (5 ), edge[9 ].push_back (4 ), edge[9 ].push_back (6 ); } bool check (int x, int num) { for (int i = 0 ; i < edge[x].size (); i++) { if (abs (num - pos[edge[x][i]]) == 1 ) { return false ; } } return true ; } void dfs (int x) { if (x == 10 ) { ans++; return ; } for (int i = 0 ; i <= 9 ; i++) { if (visit[i] == 0 ) { if (!check (x, i)) continue ; pos[x] = i; visit[i] = 1 ; dfs (x + 1 ); visit[i] = 0 ; pos[x] = -10 ; } } } int main () { start (); for (int i = 0 ; i <= 9 ; i++) pos[i] = -10 ; dfs (0 ); cout << ans; return 0 ; }
二刷换了一个写法,思路差不多,区别是先枚举,最后判断,这样写可能慢了一点,但是更清晰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include <bits/stdc++.h> using namespace std;vector<int > edge[11 ]; int pos[11 ];int ans;bool visit[10 ];void init () { for (int i=0 ;i<10 ;i++) pos[i]=-199 ; edge[0 ].push_back (1 ), edge[0 ].push_back (4 ), edge[0 ].push_back (3 ), edge[0 ].push_back (5 ); edge[1 ].push_back (0 ), edge[1 ].push_back (5 ), edge[1 ].push_back (2 ), edge[1 ].push_back (4 ), edge[1 ].push_back (6 ); edge[2 ].push_back (1 ), edge[2 ].push_back (6 ), edge[2 ].push_back (5 ); edge[3 ].push_back (4 ), edge[3 ].push_back (7 ), edge[3 ].push_back (8 ), edge[3 ].push_back (0 ); edge[4 ].push_back (3 ), edge[4 ].push_back (8 ), edge[4 ].push_back (5 ), edge[4 ].push_back (0 ), edge[4 ].push_back (9 ), edge[4 ].push_back (7 ), edge[4 ].push_back (1 ); edge[5 ].push_back (1 ), edge[5 ].push_back (4 ), edge[5 ].push_back (9 ), edge[5 ].push_back (6 ), edge[5 ].push_back (0 ), edge[5 ].push_back (2 ), edge[5 ].push_back (8 ); edge[6 ].push_back (2 ), edge[6 ].push_back (5 ), edge[6 ].push_back (1 ), edge[6 ].push_back (9 ); edge[7 ].push_back (3 ), edge[7 ].push_back (8 ), edge[7 ].push_back (4 ); edge[8 ].push_back (7 ), edge[8 ].push_back (4 ), edge[8 ].push_back (9 ), edge[8 ].push_back (3 ), edge[8 ].push_back (5 ); edge[9 ].push_back (8 ), edge[9 ].push_back (5 ), edge[9 ].push_back (4 ), edge[9 ].push_back (6 ); } bool judge (int x) { int l=edge[x].size (); for (int i=0 ;i<l;i++) { int y=edge[x][i]; if (abs (pos[x]-pos[y])==1 ) return false ; } return true ; } void dfs (int x) { if (x==10 ) { for (int i=0 ;i<9 ;i++) { if (!judge (i)) return ; } ans++; } else { for (int i=0 ;i<10 ;i++) { if (visit[i]) continue ; visit[i]=1 ; pos[x]=i; dfs (x+1 ); visit[i]=0 ; } } } int main () { init (); dfs (0 ); cout<<ans; return 0 ; }
快速排序 考察快排的基本思路,学过的应该秒出答案吧 (不好意思我不会现学的) 其实先学先用也可以,题目给了快排的思路,可以照葫芦画瓢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include <stdio.h> void swap (int a[], int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; } int partition (int a[], int p, int r) { int i = p; int j = r + 1 ; int x = a[p]; while (1 ) { while (i < r && a[++i] < x) ; while (a[--j] > x) ; if (i >= j) break ; swap (a, i, j); } swap (a, p, j); return j; } void quicksort (int a[], int p, int r) { if (p < r) { int q = partition (a, p, r); quicksort (a, p, q - 1 ); quicksort (a, q + 1 , r); } } int main () { int i; int a[] = {5 , 13 , 6 , 24 , 2 , 8 , 19 , 27 , 6 , 12 , 1 , 17 }; int N = 12 ; quicksort (a, 0 , N - 1 ); for (i = 0 ; i < N; i++) printf ("%d " , a[i]); printf ("\n" ); return 0 ; }
寒假作业 很有意思的一道dfs题,思路和之前的那道题思路很像,边搜边排除,到最后能搜完的就是正解,思路出来了代码很好写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 #include <bits/stdc++.h> using namespace std;int ans;bool visit[14 ];void dfs (int cnt) { if (cnt == 1 ) { for (int i = 1 ; i <= 13 ; i++) { for (int j = 1 ; j <= 13 - i; j++) { if (visit[i] || visit[j]) continue ; if (i + j > 13 ) continue ; if (i == j) continue ; visit[i] = visit[j] = visit[i + j] = true ; dfs (2 ); visit[i] = visit[j] = visit[i + j] = false ; } } } if (cnt == 2 ) { for (int i = 1 ; i <= 13 ; i++) for (int j = 1 ; j < i; j++) { if (visit[i] || visit[j] || visit[i - j]) continue ; if (j == (i - j)) continue ; visit[i] = visit[j] = visit[i - j] = true ; dfs (3 ); visit[i] = visit[j] = visit[i - j] = false ; } } if (cnt == 3 ) { for (int i = 1 ; i <= 13 ; i++) for (int j = 1 ; j <= (13 / i); j++) { if (visit[i] || visit[j] || visit[i * j]) continue ; if (i == j || i == i * j || j == i * j) continue ; visit[i] = visit[j] = visit[i * j] = true ; dfs (4 ); visit[i] = visit[j] = visit[i * j] = false ; } } if (cnt == 4 ) { for (int i = 1 ; i <= 13 ; i++) for (int j = 1 ; j < i; j++) { if (i % j != 0 ) continue ; if (visit[i] || visit[j] || visit[i / j]) continue ; if (i == j || i == i / j || j == i / j) continue ; ans++; } } } int main () { dfs (1 ); cout << ans; return 0 ; }
剪邮票 也是dfs题,我当时自己写的时候犯了一个错误,首先讲一下我的思路:首先用dfs生成五个不相同的数字,然后将这5个数字在图上对应的地方标记,然后dfs图看看是否为连通块。但是要注意:假如你使用dfs搜出来的数字组合,你搜出来的序列是有重复的!12345和54321是一种情况! ,当时我第一次跑的时候答案是一万多,后来想了一个多小时,才发现是这个错了,解决方式很简单。每一种情况会被重复5!次,结果除一下5!就行了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #include <bits/stdc++.h> using namespace std;int pos_x[] = {0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 };int pos_y[] = {0 , 0 , 1 , 2 , 3 , 0 , 1 , 2 , 3 , 0 , 1 , 2 , 3 , 0 , 1 , 2 , 3 };bool visit[13 ];bool edge[4 ][5 ];int ans;int dirx[] = {0 , 0 , 1 , -1 };int diry[] = {1 , -1 , 0 , 0 };bool sum[100000 ];void dfs (int x, int y, int &cnt) { if (!(x <= 2 && x >= 0 && y <= 3 && y >= 0 )) return ; if (edge[x][y] == false ) return ; cnt++; edge[x][y] = false ; for (int i = 0 ; i < 4 ; i++) { int x1 = x + dirx[i]; int y1 = y + diry[i]; dfs (x1, y1, cnt); } } void check () { memset (edge, 0 , sizeof (edge)); int x1; int y1; for (int i = 1 ; i <= 12 ; i++) { if (visit[i]) { edge[pos_x[i]][pos_y[i]] = true ; x1 = pos_x[i]; y1 = pos_y[i]; } } int cnt = 0 ; dfs (x1, y1, cnt); if (cnt == 5 ) { ans++; } } void select (int cnt) { if (cnt > 5 ) { check (); return ; } else { for (int i = 1 ; i <= 12 ; i++) { if (visit[i] == false ) { visit[i] = true ; select (cnt + 1 ); visit[i] = false ; } } } } int main () { select (1 ); cout << ans / (5 * 4 * 3 * 2 * 1 ); return 0 ; }
二刷换了一个写法,更清晰一点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #include <bits/stdc++.h> using namespace std;int maze[4 ][5 ];int visit[4 ][5 ];int posx[]={0 ,1 ,1 ,1 ,1 ,2 ,2 ,2 ,2 ,3 ,3 ,3 ,3 ,4 ,4 ,4 ,4 };int posy[]={0 ,1 ,2 ,3 ,4 ,1 ,2 ,3 ,4 ,1 ,2 ,3 ,4 ,1 ,2 ,3 ,4 };int dirx[]={0 ,0 ,-1 ,1 };int diry[]={1 ,-1 ,0 ,0 };int ans;int cnt;void get (int x,int y) { for (int i=0 ;i<4 ;i++) { int rempx=x+dirx[i]; int rempy=y+diry[i]; if (!(rempx<=3 &&rempx>=1 &&rempy<=4 &&rempy>=1 )) continue ; if (maze[rempx][rempy]&&visit[rempx][rempy]==false ) { visit[rempx][rempy]=true ; get (rempx,rempy); } } } bool judge () { cnt=0 ; memset (visit,0 ,sizeof (visit)); for (int i=1 ;i<=3 ;i++) for (int j=1 ;j<=4 ;j++) { if (maze[i][j]&&visit[i][j]==false ) { visit[i][j]=1 ; get (i,j); cnt++; } } if (cnt==1 ) return true ; else return false ; } void dfs (int num) { if (num<=5 ) { for (int i=1 ;i<=12 ;i++) { int x=posx[i]; int y=posy[i]; if (maze[x][y]) continue ; maze[x][y]=true ; dfs (num+1 ); maze[x][y]=false ; } } else { if (judge ()) ans++; } } int main () { dfs (1 ); cout<<ans/(5 *4 *3 *2 *1 ); return 0 ; }
四平方和 这道题是真的离谱。。。。我当时一开始写,想了一堆优化方案。。。 我的自己思路是这样的; 首先枚举后两项,将大的数字组合先存起来,然后从头枚举前两个小的,再二分查找满足条件的后两项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 #include <bits/stdc++.h> using namespace std;long long num;int cnt = 0 ;struct node { int c, d; int sumcd; } edge[10000000 ]; bool cmp (node x, node y) { if (x.sumcd!=y.sumcd) return x.sumcd < y.sumcd; if (x.c!=y.c) return x.c<y.c; return x.d<y.d; } bool check (int a, int b, int mid) { if (a * a + b * b + edge[mid].sumcd >= num) return true ; else return false ; } void get_ans () { for (int i = 0 ; i*i <=num; i++) { for (int j = i; j*j+i*i <=num; j++) { cnt++; edge[cnt].c = i; edge[cnt].d = j; edge[cnt].sumcd = i * i + j * j; } } sort (edge + 1 , edge + cnt + 1 , cmp); for (int i = 0 ; i*i <= num; i++) for (int j = i; j*j+i*i <= num; j++) { int left = 1 ; int right = cnt; int ans = -1 ; while (left <= right) { int mid = (left + right) >> 1 ; if (check (i, j, mid)) { ans = mid; right = mid - 1 ; } else left = mid + 1 ; } if (i * i + j * j + edge[ans].sumcd == num) { cout << i << " " << j << " " << edge[ans].c << " " << edge[ans].d; return ; } } } int main () { ios::sync_with_stdio (false ); cin >> num; get_ans (); return 0 ; }
但是!这道题压根不用这么麻烦!!!! 四重暴力循环会超时,但是可以三维优化一下就可以解决问题!!! 该说不愧是暴力杯啊???真有你的蓝桥杯!!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> using namespace std;int main () { ios::sync_with_stdio (false ); long long num; cin >> num; int maxn = sqrt (num); for (int i = 0 ; i <= maxn; i++) for (int j = i; j <= maxn; j++) for (int z = j; z <= maxn; z++) { int remp = sqrt (num - (i * i + j * j + z * z)); if (remp * remp + i * i + j * j + z * z == num) { cout << i << " " << j << " " << z << " " << remp; return 0 ; } } return 0 ; }
另外再加dxy大佬的另一个解法: 鸣谢dxy大佬!!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <bits/stdc++.h> using namespace std;typedef long long ll;#define pii pair<int,int> const int mod=1e9 +7 ;const int INF=0x3f3f3f3f ;const int N=5e6 +5 ;int a[N],b[N];int main () { ios::sync_with_stdio (false ); cin.tie (0 ),cout.tie (0 ); int n; cin>>n; memset (a,-1 ,sizeof a); for (int i=0 ;i*i<=n;i++){ for (int j=i;j*j+i*i<=n;j++){ int temp=i*i+j*j; if (a[temp]!=-1 ) continue ; a[temp]=i; b[temp]=j; } } for (int i=0 ;i*i<=n;i++){ for (int j=i;i*i+j*j<=n;j++){ int temp=n-i*i-j*j; if (a[temp]!=-1 ){ cout<<i<<" " <<j<<" " <<a[temp]<<" " <<b[temp]<<"\n" ; return 0 ; } } } return 0 ; }
(我是伞兵)
密码脱落 一道区间dp模版题,理解了思路不难 贴一个区间dp模板
1 2 3 4 5 6 7 8 9 10 11 12 13 区间dp模板 memset (dp, 0 , sizeof (dp)); for (int len = 2 ; len <= n; len++) { for (int i = 1 ; i + len - 1 < n; ++i) { int j = i + len - 1 ; for (int k = i; k <= j; ++k) } }
下面是全代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <bits/stdc++.h> using namespace std;int dp[10000 ][10000 ];int main () { string str; cin >> str; int len = str.length (); for (int l = 1 ; l <= len; l++) { for (int i = 0 ; i + l - 1 < len; i++) { int j = i + l - 1 ; if (l == 1 ) { dp[i][j] = 1 ; } else { dp[i][j] = max (dp[i + 1 ][j], dp[i][j - 1 ]); if (str[i] == str[j]) { dp[i][j] = max (dp[i][j], dp[i + 1 ][j - 1 ] + 2 ); } } } } cout << len - dp[0 ][len - 1 ]; return 0 ; }
消除尾一
代码填空,理解题意就好了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> void f (int x) { int i; for (i = 0 ; i < 32 ; i++) printf ("%d" , (x >> (31 - i)) & 1 ); printf (" " ); x = x & (x + 1 ); for (i = 0 ; i < 32 ; i++) printf ("%d" , (x >> (31 - i)) & 1 ); printf ("\n" ); } int main () { f (103 ); f (12 ); return 0 ; }