参考wp:https://blog.csdn.net/qq_33957603/article/details/124156811
补题链接:https://codeforces.com/gym/103055
A. League of Legends
签到题
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 (0 ); cin.tie (0 ); cout.tie (0 ); long long blue=0 ,red=0 ; for (int i=0 ;i<5 ;i++){ long long x; cin>>x; blue+=x; } for (int i=0 ;i<5 ;i++){ long long x; cin>>x; red+=x; } if (blue>=red){ cout<<"Blue" ; } else { cout<<"Red" ; } }
C. Cube
题目大意: 给出八个点,求这八个点能否构成正方体
思路 枚举所有的边,数量满足12/12/4(边长,面对角线,体对角线),且长度平方满足1:2:3,即可证明为立方体。
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 #include <bits/stdc++.h> using namespace std;long long d[100 ];int x[9 ],y[9 ],z[9 ];int main () { ios::sync_with_stdio (0 ); cin.tie (0 ); cout.tie (0 ); int t; cin>>t; while (t--){ for (int i = 1 ;i<=8 ;i++) { cin>>x[i]>>y[i]>>z[i]; } int k = 0 ; for (int i = 1 ;i<=8 ;i++) { for (int j = i+1 ;j<=8 ;j++) { d[++k] = (x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i])+(z[j]-z[i])*(z[j]-z[i]); } } sort (d+1 ,d+k+1 ); if (d[1 ]==0 ) { cout<<"NO" <<endl; }else if (d[1 ]==d[12 ]&&d[13 ]==d[24 ]&&d[25 ]==d[28 ]&&d[13 ]==2 *d[1 ]&&d[25 ]==3 *d[1 ]) { cout<<"YES" <<endl; }else { cout<<"NO" <<endl; } } return 0 ; }
F. Fair Distribution 题目大意: 有n个机器人和m个能量块,有一个枪手能够有两种操作,一是销毁一个机器人,二是创造一个能量块。每次操作都会有一个代价,求最小的代价能够使得能量块的数量能够被机器人的数量整除(也就是均分)
思路:
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 #include <iostream> #include <cmath> using namespace std;typedef long long ll;int main () { int t; cin >> t; while (t--) { ll n, m; cin >> n >> m; if (n >= m) cout << n - m << endl; else { ll s = sqrt (m); ll t = 1e8 + 10 ; for (int i = 1 ; i <= s; i++) { if (m % i == 0 ) { if (n >= i) { t = min (t, abs (n - i)); } if (n >= m / i) { t = min (t, abs (n - m / i)); } } else { if (n >= i) t = min (t, n - i + abs (m % i - i)); if (n >= m / i + 1 ) t = min (t, n - m / i -1 + abs (m/i+1 -m%(m/i+1 ))); } } cout << t << endl; } } return 0 ; }
G Wall Game
题目大意: n组输入,每组输入三个数字,第一个数字代表操作类型, 第二三个数字代表坐标。 操作1:在整个图上添加点,并和相邻的点联通 操作2:查询这个点的整个联通的快,输出整个块的边的数量(点与点间边将被忽略)
思路: 并查集+离散化
推导发现:
若只有一个点:边=6
若多个点相连:n个点有x条重边,边数=6n-2 x
map mp;不能使用unordered_map,因为unordered_map是基于离散化的,对node节点要提供离散化函数。
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 #include <iostream> #include <map> using namespace std;typedef long long LL;const int N = 5e5 +10 ; int p[N];int siz[N] ; int rpp[N]; int idx = 0 ; int n,m;int dx[] = {1 ,1 ,0 ,0 ,-1 ,-1 };int dy[] = {0 ,-1 ,-1 ,1 ,0 ,1 };int find (int x) { if (p[x] != x) p[x] = find (p[x]); return p[x]; } struct node { int x, y; node (){} node (int x, int y) : x (x), y (y) {} bool operator < (const node& b) const { if (x == b.x) { return y < b.y; } else { return x < b.x; } } } arr[N]; map<node,int > mp; void init () { for (int i = 1 ; i < N; i++) { p[i] = i; siz[i] = 1 ; } } void merge (int x, int y) { x = find (x); y = find (y); if (x!=y) { if (siz[x] < siz[y]) swap (x,y); p[y] = x; siz[x] += siz[y]; rpp[x] += rpp[y] + 1 ; } } int main () { ios::sync_with_stdio (0 ); cin.tie (0 ); cin >> n; init (); int op,x,y; while (n--) { cin >> op >> x >> y; if (op == 1 ) { node nd = node (x,y); if (!mp.count (nd)) { mp[nd] = ++idx; for (int i = 0 ; i < 6 ; i++) { int nx = x + dx[i]; int ny = y + dy[i]; node ndd = node (nx,ny); if (mp.count (ndd)) { if (find (mp[ndd]) != find (mp[nd])) { merge (mp[ndd], mp[nd]); } else { rpp[find (mp[nd])]++; } } } } } else if (op == 2 ) { node nd = node (x,y); if (mp.count (nd)) { int root = find (mp[nd]); cout << siz[root]*6 - 2 *rpp[root] << endl; } else { cout << 6 << endl; } } } }
J. Grammy and Jewelry 题目大意: 给定一个权值全为1(消耗1单位的时间)的无向图,n个点,m条边,除去第一个顶点外其余顶点均有珠宝。
从起点出发,拿起和放下珠宝不占时间,每次只能携带一件珠宝,当珠宝放回七点即获得该珠宝。
每个点的珠宝是无限的。
求x在[1,T]中的每个时间段内能获得的最大珠宝数。
思路 用迪杰斯特拉(或BFS)求最短路径,然后用完全背包问题求解
v = 路径长度*2(往返)
w = 该点珠宝数
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 87 88 89 90 91 92 93 #include <bits/stdc++.h> using namespace std;int n,m,T; const int N = 6100 ;int h[N],ne[N],e[N],idx;int dist[N];int st[N]; int jew[N]; int v[N],w[N],f[N]; void add (int a, int b) { e[idx] = b; ne[idx] = h[a]; h[a] = idx++; } void Dijkstra () { memset (dist,0x3f ,sizeof (dist)); dist[1 ] = 0 ; queue<int > q; q.push (1 ); st[1 ] = 1 ; while (q.size ()) { int t = q.front (); q.pop (); for (int i = h[t]; i!=-1 ;i = ne[i]) { int j = e[i]; if (!st[j]) { dist[j] = dist[t] + 1 ; q.push (j); st[j] = 1 ; } } } } int main () { ios::sync_with_stdio (0 ); cin.tie (0 ); cout.tie (0 ); memset (h,-1 , sizeof h); cin >>n >>m >>T; for (int i = 2 ; i<=n;i++) { cin >> jew[i]; } for (int j = 0 ;j<m;j++) { int a,b; cin >> a >>b; add (a,b); add (b,a); } Dijkstra (); for (int i = 2 ; i<=n;i++) { v[i] = dist[i]*2 ; w[i] = jew[i]; } for (int i = 1 ; i<=n;i++) { for (int j = v[i]; j<=T;j++) { f[j] = max (f[j], f[j-v[i]] +w[i]); } } for (int i = 1 ; i<=T;i++) { cout <<f[i] <<" " ; } }
L String Freshman
题目大意: 给出一个错误的kmp算法,问字符串T在匹配的时候答案是否与正确的kmp算法一致
思路 该kmp算法在每次匹配后都会回到字符串开头重新匹配,而正确的kmp算法应该是跳转到next数组(到当前位置为止,前缀和后缀的最长公共元素长度)里。
因此有字符和第一个字符相等(不会跳转到被匹配的字符串开头)即为错误。
M. Game Theory
题目大意: 老师和学生互相给对方打分(需要从自己有的分数里扣),范围在[1,20],假设老师打了x,学生打了y。如果x>y学生多给老师10分,反之老师多给学生10分。 问如果老师随机出值,每个学生可以自己选择值,面对n个学生的情况下(对每个学生都是独立情况)老师的期望得分是多少。
思路 通过代码计算期望,得出答案恒为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 #include <bits/stdc++.h> using namespace std; int main () { ios::sync_with_stdio (0 ); cin.tie (0 ); cout.tie (0 ); int n; cin>>n; double max=0 ,x=0 ; for (int y = 1 ; y <=20 ;y++) { double tot = 0 ; for (int x = 1 ; x<=20 ;x++) { double xue = 0 ; double lao = 0 ; xue += x; lao -= x; xue -= y; lao += y; if (x>y) { xue-=10 ; lao+=10 ; } if (x<y) { xue+=10 ; lao-=10 ; } tot+=lao; } cout << tot; cout <<endl; } printf ("%.4f" ,0 ); }