DISCO Presents Discovery Channel Code Contest 2020 Qual 题解
A
枚举一下
#include <bits/stdc++.h> using namespace std; int main() { int x, y; cin >> x >> y; int ans = 0; if(x == 1) { ans += 300000; } if(x == 2) { ans += 200000; } if(x == 3) { ans += 100000; } if(y == 1) { ans += 300000; } if(y == 2) { ans += 200000; } if(y == 3) { ans += 100000; } if(x == 1 && y == 1) { ans += 400000; } cout << ans << '\n'; return 0; }
B
枚举一下断点
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<ll> a(n); ll sum = 0; for(int i = 0; i < n; ++i) { cin >> a[i]; sum += a[i]; } ll pre = 0, ans = sum; for(int i = 0; i < n; ++i) { pre += a[i]; ans = min(ans, abs(2LL * pre - sum)); } cout << ans << '\n'; return 0; }
C
有草莓的行分段涂 没有的和有的合并
#include <bits/stdc++.h> using namespace std; int main() { int n, m, k; cin >> n >> m >> k; int cnt = 0; vector<vector<int> > a(n, vector<int>(m, 0)); for(int i = 0; i < n; ++i) { string s; cin >> s; for(int j = 0; j < m; ++j) { if(s[j] == '#') { a[i][j] = ++cnt; for(int k = j - 1; ~k; --k) { if(a[i][k] || s[k] == '#') { break; } a[i][k] = cnt; } for(int k = j + 1; k < m; ++k) { if(a[i][k] || s[k] == '#') { break; } a[i][k] = cnt; } } } } cout << '\n'; for(int i = 0; i < n; ++i) for(int j = 0; j < m; ++j) { if(!a[i][j]) { continue; } for(int k = i - 1; ~k; --k) { if(a[k][j]) { break; } a[k][j] = a[i][j]; } for(int k = i + 1; k < n; ++k) { if(a[k][j]) { break; } a[k][j] = a[i][j]; } } for(int i = 0; i < n; ++i) { for(int j = 0; j < m; ++j) { cout << a[i][j] << ' '; } cout << '\n'; } return 0; }
D
思考一下发现 顺序与答案无关 (一个不严谨的证明:和是不变的 所以无关)
如果不进位的话 答案就是$\sum_{i=1}^{n}{d_i}-1$
考虑进位 那么每进一次位就是多出来一个1
设$sum=\sum_{i=1}^{n}{d_i*c_i}$
那么每次进位相当于$sum - 9$
如果$sum<10$停止
那么答案就是$\sum_{i=1}^{n}{d_i}-1 + \frac{\sum_{i=1}^{n}{d_i*c_i} - 1}{9}$
#include <bits/stdc++.h> using namespace std; using ll = long long; const int maxn = 2e5 + 5; int n; ll d[maxn], c[maxn]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; for(int i = 1; i <= n; ++i) { cin >> d[i] >> c[i]; } ll sum = 0, ans = 0; for(int i = 1; i <= n; ++i) { ans += c[i]; sum += d[i] * c[i]; } cout << ans - 1 + (sum - 1) / 9 << '\n'; return 0; }
E
这个题不错
如果能找出一个长度为$n$且红球蓝球数量差$<=1$的序列 并且知道其中一个红球和一个蓝球的位置 那么就能问出来所有了
由于红球有n个 蓝球有n个 这样的序列肯定是存在的
设$ask(l, r)$表示询问$l-r$ 并且$r - l + 1 = n$
假设$ask(1,n)=R$ 那么 $ask(n + 1, 2n) = B$
并且存在某一个$i$使得$ask(i,i+n-1)$和$ask(i+1,i+n)$不同
接着可以发现 这样的i是可以二分得出的
那么先二分出这样的分界点 然后将其他所有点带进这个序列询问即可
花费的询问次数是$2n-2 + log(n)+1 < 210$
#include <bits/stdc++.h> using namespace std; const int maxn = 205; int n, L, R; int ans[maxn]; int Ask(int l, int r) { cout << '?'; for(int i = l; i <= r; ++i) { cout << ' ' << i; } cout << '\n'; string ret; cin >> ret; return ret == "Red" ? -1 : 1; } int Ask(int x) { cout << '?' << ' ' << x; for(int i = 1; i <= 2 * n; ++i) { if(i != L && i != R && (L < i && i < R) != (L < x && x < R)) { cout << ' ' << i; } } cout << '\n'; string ret; cin >> ret; return ret == "Red" ? -1 : 1; } int main() { cin >> n; int prv = Ask(1, n); int l = 1, r = n + 1; while(r - l > 1) { int mid = l + r >> 1; if(Ask(mid, mid + n - 1) == prv) { l = mid; } else { r = mid; } } ans[l] = prv; ans[l + n] = -prv; L = l; R = l + n; for(int i = 1; i <= 2 * n; ++i) { if(i != L && i != R) { ans[i] = Ask(i); } } cout << "! "; for(int i = 1; i <= 2 * n; ++i) { cout << (ans[i] == -1 ? 'R' : 'B'); } cout << '\n'; return 0; }
F
好难啊
先将方阵分解成小方阵 小方阵中$d=1$ 也就是每次只走一步 不同方阵之间互相独立
小方阵的长宽分别是$n/gcd(n,d)$和$m/gcd(m,d)$
然后考虑方案
只有向下和不动方案是是$2^{m/gcd(m,d)}-1$
只有向左和不动的方案是$2^{n/gcd(n,d)}-1$
同时向下和向左的方案是$2^{gcd(n/gcd(n,d), m/gcd(m,d))}-1$
最后一个比较抽象 这么考虑 把方阵按对角线分组 这样就有$gcd(n/gcd(n,d), m/gcd(m,d))$组
每一组必须行动一致 向左或向下 这样为什么是对的 因为对于每个格子单独考虑 每一秒都只有一个人进一个人出 不会撞上
如果对角线行动不一致 那么就会撞上
最后乘上矩形数即可
这种问题就是置换群的套路 分解成循环节 问题变得简单后再分类讨论
#include <bits/stdc++.h> using namespace std; using ll = long long; const int P = 1e9 + 7; ll h, w, t; ll power(ll x, ll t) { ll ret = 1; for(; t; t >>= 1, x = x * x % P) { if(t & 1) { ret = ret * x % P; } } return ret; } int main() { cin >> h >> w >> t; ll n = h / __gcd(h, t), m = w / __gcd(w, t); ll tmp = (power(2LL, n) + power(2LL, m) + power(2LL, __gcd(n, m)) - 3 + P) % P; ll c = __gcd(h, t) * __gcd(w, t); cout << power(tmp, c) << '\n'; return 0; }