2018年浙江中医药大学程序设计竞赛 Solution
签。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 puts("Helle World!"); 7 return 0; 8 }
Solved.
- 如果 $n >= m 直接赢$
- 否则 $易知必败局面是当前剩余数是(n + 1)的倍数$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int n, m; 6 7 int main() 8 { 9 while(~scanf("%d %d", &n, &m)) 10 { 11 if(n >= m) 12 { 13 for(int i = m; i <= n; ++i) 14 printf("%d%c", i, " \n"[i == n]); 15 } 16 else 17 { 18 if(m % (n + 1) == 0) puts("You are loser"); 19 else printf("%d\n", m % (n + 1)); 20 } 21 } 22 return 0; 23 }
温暖的签。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 100010 6 int n; 7 ll m, x, Max; 8 9 int main() 10 { 11 while (scanf("%d%lld", &n, &m) != EOF) 12 { 13 Max = 0; 14 for (int i = 1; i <= n; ++i) 15 { 16 scanf("%lld", &x); 17 Max = max(Max, x); 18 } 19 printf("%lld\n", max(0ll, Max - m)); 20 } 21 return 0; 22 }
Solved.
题意:
有$n个队列,两种操作$
- $1\; x\; y\; z \;\;将编号属于[x, y]的队列最后加入一个z$
- $2\; x\; y\; z \;\; 询问编号属于[x, y]的所有队列中的所有人中第z大的数是多少$
思路:
本来想分块维护三个BIT,但是发现空间炸了。
那找第$k大的数可以二分,多次询问,就整体二分$
对于每个询问二分答案,在时间线中,在你前面的 并且 值小于你二分的答案就加入线段树
查询的时候直接查,记得更新k,然后将询问分组即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 50010 6 int n, m, Q; 7 8 namespace SEG 9 { 10 ll sum[N << 2], lazy[N << 2]; 11 void pushdown(int id, int l, int mid, int r) 12 { 13 if (!lazy[id]) return; 14 sum[id << 1] += 1ll * (mid - l + 1) * lazy[id]; 15 lazy[id << 1] += lazy[id]; 16 sum[id << 1 | 1] += 1ll * (r - mid) * lazy[id]; 17 lazy[id << 1 | 1] += lazy[id]; 18 lazy[id] = 0; 19 } 20 void update(int id, int l, int r, int ql, int qr, int v) 21 { 22 if (l >= ql && r <= qr) 23 { 24 sum[id] += 1ll * v * (r - l + 1); 25 lazy[id] += v; 26 return; 27 } 28 int mid = (l + r) >> 1; 29 pushdown(id, l, mid, r); 30 if (ql <= mid) update(id << 1, l, mid, ql, qr, v); 31 if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, v); 32 sum[id] = sum[id << 1] + sum[id << 1 | 1]; 33 } 34 ll query(int id, int l, int r, int ql, int qr) 35 { 36 // printf("%d %d %d %d\n", l, r, ql, qr); 37 if (l >= ql && r <= qr) return sum[id]; 38 int mid = (l + r) >> 1; 39 pushdown(id, l, mid, r); 40 ll res = 0; 41 if (ql <= mid) res += query(id << 1, l, mid, ql, qr); 42 if (qr > mid) res += query(id << 1 | 1, mid + 1, r, ql, qr); 43 return res; 44 } 45 } 46 47 struct node 48 { 49 int op, l, r, z, id; 50 node () {} 51 node (int op, int l, int r, int z, int id) : op(op), l(l), r(r), z(z), id(id) {} 52 }q[N << 1], ql[N << 1], qr[N << 1]; 53 int ans[N]; 54 55 void CDQ(int L, int R, int l, int r) 56 { 57 if (L > R) return; 58 if (l == r) 59 { 60 for (int i = L; i <= R; ++i) if (q[i].op == 2) 61 ans[q[i].id] = l; 62 return; 63 } 64 int mid = (l + r) >> 1; 65 int cnt_ql = 0, cnt_qr = 0; 66 for (int i = L; i <= R; ++i) 67 { 68 if (q[i].op == 1) 69 { 70 if (q[i].z <= mid) 71 { 72 SEG::update(1, 1, n, q[i].l, q[i].r, 1); 73 ql[++cnt_ql] = q[i]; 74 } 75 else 76 qr[++cnt_qr] = q[i]; 77 } 78 else 79 { 80 ll sze = SEG::query(1, 1, n, q[i].l, q[i].r); 81 if (sze < q[i].z) 82 { 83 q[i].z -= sze; 84 qr[++cnt_qr] = q[i]; 85 } 86 else 87 ql[++cnt_ql] = q[i]; 88 } 89 } 90 for (int i = 1; i <= cnt_ql; ++i) if (ql[i].z <= mid) SEG::update(1, 1, n, ql[i].l, ql[i].r, -1); 91 for (int i = 1; i <= cnt_ql; ++i) q[L + i - 1] = ql[i]; 92 for (int i = 1; i <= cnt_qr; ++i) q[L + cnt_ql + i - 1] = qr[i]; 93 CDQ(L, L + cnt_ql - 1, l, mid); 94 CDQ(L + cnt_ql, R, mid + 1, r); 95 } 96 97 int main() 98 { 99 while (scanf("%d%d", &n, &Q) != EOF) 100 { 101 m = 0; 102 memset(ans, 0, sizeof ans); 103 for (int i = 1, op, x, y, z; i <= Q; ++i) 104 { 105 scanf("%d%d%d%d", &op, &x, &y, &z); 106 if (op == 1) q[++m] = node(1, x, y, -z, i); 107 else q[++m] = node(2, x, y, z, i); 108 } 109 CDQ(1, m, -n, -1); 110 for (int i = 1; i <= Q; ++i) if (ans[i]) 111 printf("%d\n", -ans[i]); 112 } 113 return 0; 114 }
演了一波,小dp写成最短路、搜索可还行
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const int maxn = 1e3 + 10; 8 9 int n; 10 ll a[maxn]; 11 ll dis[maxn]; 12 int vis[maxn]; 13 14 void BFS() 15 { 16 memset(vis, 0, sizeof vis); 17 memset(dis, 0x3f, sizeof dis); 18 vis[1] = 1; 19 dis[1] = 0; 20 queue<int>q; 21 q.push(1); 22 while(!q.empty()) 23 { 24 int u = q.front(); 25 q.pop(); 26 if(!vis[min(n, u + 5)]) 27 { 28 dis[min(n, u + 5)] = dis[u] + 2; 29 vis[min(n, u + 5)] = 1; 30 q.push(min(n, u + 5)); 31 } 32 33 if(!vis[min(n * 1ll, a[u])]) 34 { 35 dis[min(n * 1ll, a[u])] = dis[u] + 2; 36 vis[min(n * 1ll, a[u])] = 1; 37 q.push(min(n * 1ll, a[u])); 38 } 39 } 40 } 41 42 int main() 43 { 44 while(~scanf("%d", &n)) 45 { 46 n++; 47 for(int i = 1; i <= n - 1; ++i) 48 { 49 scanf("%d", a + i); 50 a[i] = min(a[i], n * 1ll); 51 } 52 BFS(); 53 printf("%lld\n", dis[n]); 54 } 55 return 0; 56 }
Solved.
两次搜索,搜'L' -> 'W' 和 'Q' -> 'W' 枚举'W'位置更新答案
薛佬交了三发,Rejudge后第一发其实就过
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int INF = 0x3f3f3f3f; 6 const int maxn = 2e3 + 10; 7 8 int n, m; 9 int vis[maxn][maxn]; 10 int dis1[maxn][maxn]; 11 int dis2[maxn][maxn]; 12 char mp[maxn][maxn]; 13 int dir[4][2] = {1, 0, 0 ,1 ,-1, 0 ,0, -1}; 14 15 struct node{ 16 int x, y; 17 node(){} 18 node(int x,int y):x(x), y(y){}; 19 }Q,L; 20 21 bool check(int x, int y) 22 { 23 if(x < 1 || x > n || y < 1 || y > m || mp[x][y] == '#' || vis[x][y]) return false; 24 else return true; 25 } 26 27 vector<node>W; 28 29 void BFS1() 30 { 31 memset(vis, 0, sizeof vis); 32 memset(dis1, INF, sizeof dis1); 33 vis[L.x][L.y] = 1; 34 dis1[L.x][L.y] = 0; 35 queue<node>q; 36 q.push(L); 37 while(!q.empty()) 38 { 39 node st = q.front(); 40 q.pop(); 41 for(int i = 0 ; i< 4; ++i) 42 { 43 node now; 44 now.x = st.x + dir[i][0]; 45 now.y = st.y + dir[i][1]; 46 if(check(now.x, now.y)) 47 { 48 vis[now.x][now.y] = 1; 49 dis1[now.x][now.y] = dis1[st.x][st.y] + 1; 50 q.push(now); 51 } 52 } 53 } 54 } 55 56 void BFS2() 57 { 58 memset(vis, 0, sizeof vis); 59 memset(dis2, INF, sizeof dis2); 60 vis[L.x][L.y] = 1; 61 dis2[Q.x][Q.y] = 0; 62 queue<node>q; 63 q.push(Q); 64 while(!q.empty()) 65 { 66 node st = q.front(); 67 q.pop(); 68 for(int i = 0 ; i< 4; ++i) 69 { 70 node now; 71 now.x = st.x + dir[i][0]; 72 now.y = st.y + dir[i][1]; 73 if(check(now.x, now.y)) 74 { 75 vis[now.x][now.y] = 1; 76 dis2[now.x][now.y] = dis2[st.x][st.y] + 1; 77 q.push(now); 78 } 79 } 80 } 81 } 82 83 int main() 84 { 85 while(~scanf("%d %d", &n, &m)) 86 { 87 for(int i = 1; i <= n; ++i) 88 { 89 for(int j = 1; j <= m; ++j) 90 { 91 scanf(" %c", &mp[i][j]); 92 if(mp[i][j] == 'Q') 93 { 94 Q = node(i, j); 95 } 96 else if(mp[i][j] == 'L') 97 { 98 L = node(i, j); 99 } 100 else if(mp[i][j] == 'W') 101 { 102 W.push_back(node(i, j)); 103 } 104 } 105 } 106 BFS1(); 107 BFS2(); 108 int ans = INF; 109 for(auto it: W) 110 { 111 ans = min(dis1[it.x][it.y] + dis2[it.x][it.y], ans); 112 } 113 printf("%d\n", ans); 114 } 115 return 0; 116 }
string.find()
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int n; 6 string s; 7 8 int main() 9 { 10 ios::sync_with_stdio(false); 11 cin.tie(0); 12 cout.tie(0); 13 while(cin >> n) 14 { 15 int sum = 0; 16 for(int i = 1; i <= n; ++i) 17 { 18 cin >> s; 19 if(s.find("zailaiyihe") != s.npos) sum++; 20 } 21 printf("%d\n", sum); 22 } 23 return 0; 24 }
线性推
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 10010 6 const ll MOD = (ll)100000007; 7 int n; 8 ll f[N], sum[2]; 9 10 int main() 11 { 12 f[0] = 1; 13 sum[0] = 1, sum[1] = 0; 14 for (int i = 1; i <= 10000; ++i) 15 { 16 f[i] = f[i - 1]; 17 f[i] = (f[i] + sum[i & 1]) % MOD; 18 sum[i & 1] = (sum[i & 1] + f[i]) % MOD; 19 } 20 while (scanf("%d", &n) != EOF) printf("%lld\n", f[n]); 21 return 0; 22 }
题意:
规则:
五张牌均严格小于5,五张牌的和小于等于10,得60分。
五张牌都是$J,Q,K$,得50分。
五张牌有四张牌相同,得40分。
如果其中三张牌的和是10的倍数,并且其他两张牌的和是10的倍数,得30分
如果其中三张牌的和是10的倍数,并且其他两张牌的和对于10的余数大于等于7,得$2*$其他两张牌的和对于10的余数
如果其中三张牌的和是10的倍数,并且其他两张牌的和对于10的余数大于等于7,得其他两张牌的和对于10的余数
其余情况不得分,同时每次只能获取最高分。
现在你手上已经有四张牌,求拿到第五张牌后的分数期望(四舍五入)
思路:
预处理出所有情况,最后遍历一次得到总分后除以13
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll MOD = 1e9 + 7; int ans[20][20][20][20][20]; void Init() { for (int a = 1; a <= 13; ++a) { for (int b = 1; b <= 13; ++b) { for (int c = 1; c <= 13; ++c) { for (int d = 1; d <= 13; ++d) { for (int e = 1; e <= 13; ++e) { if (a < 5 && b < 5 && c < 5 && d < 5 && e < 5 && a + b + c + d + e <= 10) { ans[a][b][c][d][e] = 60; } else if (a >= 11 && b >= 11 && c >= 11 && d >= 11 && e >= 11) { ans[a][b][c][d][e] = 50; } else if ((a == b && b == c && c == d) || (a == b && b == c && c == e) || (a == b && b == d && d == e) || (a == c && c == d && d == e) || (b == c && c == d && d == e)) { ans[a][b][c][d][e] = 40; } else { if ((min(10, a) + min(10, b) + min(10, c)) % 10 == 0 || (min(10, a) + min(10, b) + min(10, d)) % 10 == 0 || (min(10, a) + min(10, b) + min(10, e)) % 10 == 0 || (min(10, a) + min(10, c) + min(10, d)) % 10 == 0 || (min(10, a) + min(10, c) + min(10, e)) % 10 == 0 || (min(10, a) + min(10, d) + min(10, e)) % 10 == 0 || (min(10, b) + min(10, c) + min(10, d)) % 10 == 0 || (min(10, b) + min(10, c) + min(10, e)) % 10 == 0 || (min(10, b) + min(10, d) + min(10, e)) % 10 == 0 || (min(10, b) + min(10, d) + min(10, e)) % 10 == 0 || (min(10, c) + min(10, d) + min(10, e)) % 10 == 0) { int sum = min(10, a) + min(10, b) + min(10, c) + min(10, d) + min(10, e); if (sum % 10 == 0) ans[a][b][c][d][e] = 30; else if (sum % 10 >= 7) ans[a][b][c][d][e] = 2 * (sum % 10); else ans[a][b][c][d][e] = sum % 10; } } } } } } } } void RUN() { Init(); int t; scanf("%d", &t); while (t--) { int a, b, c, d; scanf("%d %d %d %d", &a, &b, &c, &d); int sum = 0; for (int i = 1; i <= 13; ++i) sum += ans[a][b][c][d][i]; sum = (sum / 13.0) + 0.5; printf("%d\n", sum); } } int main() { #ifdef LOCAL_JUDGE freopen("Text.txt", "r", stdin); #endif // LOCAL_JUDGE RUN(); #ifdef LOCAL_JUDGE fclose(stdin); #endif // LOCAL_JUDGE return 0; }
枚举最后一张牌,求总分,最后除以13
#include<bits/stdc++.h> using namespace std; int a[10], b[10]; int c[15]; void RUN() { int t; scanf("%d", &t); while (t--) { for (int i = 1; i <= 4; ++i) scanf("%d", a + i); b[1] = min(10, a[1]) + min(10, a[2]); b[2] = min(10, a[1]) + min(10, a[3]); b[3] = min(10, a[1]) + min(10, a[4]); b[4] = min(10, a[2]) + min(10, a[3]); b[5] = min(10, a[2]) + min(10, a[4]); b[6] = min(10, a[3]) + min(10, a[4]); b[7] = 0; int tmp = 0; for (int i = 1; i <= 4; ++i) tmp += min(10, a[i]); for (int i = 1; i <= 4; ++i) { if ((tmp - min(10, a[i])) % 10 == 0) { b[7] = 1; break; } } double ans = 0; for (int i = 1; i <= 13; ++i) { a[5] = i; //1 if (a[1] < 5 && a[2] < 5 && a[3] < 5 && a[4] < 5 && a[5] < 5 && a[1] + a[2] + a[3] + a[4] + a[5] <= 10) { ans += 60.0; continue; } //2 if (a[1] >= 11 && a[2] >= 11 && a[3] >= 11 && a[4] >= 11 && a[5] >= 11) { ans += 50.0; continue; } //3 if ((a[1] == a[2] && a[2] == a[3] && a[3] == a[4]) || (a[1] == a[2] && a[2] == a[3] && a[3] == a[5]) || (a[1] == a[2] && a[2] == a[4] && a[4] == a[5]) || (a[1] == a[3] && a[3] == a[4] && a[4] == a[5]) || (a[2] == a[3] && a[3] == a[4] && a[4] == a[5])) { ans += 40.0; continue; } //4 int sum = 0; for (int i = 1; i <= 5; ++i) sum += min(10, a[i]); if (b[7]) { if (sum % 10 == 0) ans += 30.0; else if (sum % 10 >= 7) ans += 2.0 * (sum % 10); else ans += sum % 10; continue; } //5 int res = -1; for (int j = 1; j <= 6; ++j) { if ((b[j] + min(10, a[5])) % 10 == 0) { res = sum % 10; break; } } if (res == -1) continue; if (res == 0) ans += 30.0; else if (res >= 7) ans += 2.0 * res; else if (res != -1) ans += res; } ans = (ans / 13.0) + 0.5; printf("%d\n", (int)ans); } } int main() { #ifdef LOCAL_JUDGE freopen("Text.txt", "r", stdin); #endif // LOCAL_JUDGE RUN(); #ifdef LOCAL_JUDGE fclose(stdin); #endif // LOCAL_JUDGE return 0; }
比赛的时候写丑了,同时对于题意理解不明确?(说好的一副牌呢!)