KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)
A - Century
int main() {
IOS; cin >> n;
n = n / 100 + (n % 100 != 0);
cout << n;
return 0;
}
B - 200th ABC-200
怕爆ll, 直接128
int main() {
__int128 n; int k; read(n, k);
rep (i, 1, k) {
if (n % 200 == 0) n /= 200;
else n = n * 1000 + 200;
}
write(n);
return 0;
}
C - Ringo's Favorite Numbers 2
取膜相同, 相减就是相等
int a[N];
int main() {
IOS; cin >> n; map<int, int> st; ll ans = 0;
rep (i, 1, n) {
cin >> m; ans += st[m % 200];
++st[m % 200];
}
cout << ans;
return 0;
}
D - Happy Birthday! 2
有零必定有解, 无零
则当序列为(1, 2, 4, 8, ...)的时候才无解
然而是取膜(200), 即(log2(200) < 8)
只要序列长度大于8必定有解, 状压完事
int a[N];
VI g[200];
int main() {
IOS; cin >> n; rep (i, 0, n - 1) cin >> a[i];
rep (i, 1, (1 << min(8, n)) - 1) {
int s = 0; VI cur;
rep (j, 0, min(n, 8) - 1) if (i >> j & 1)
s = (s + a[j]) % 200, cur.pb(j + 1);
if (g[s].empty()) { swap(g[s], cur); continue; }
cout << "Yes
" << g[s].size();
for (auto &j : g[s]) cout << ' ' << j;
cout << '
' << cur.size();
for (auto &j : cur) cout << ' ' << j;
return 0;
}
cout << "No";
return 0;
}
E - Patisserie ABC 2
容斥, 我们首先要找到三个数字的和,
先把每个数字(x leqslant n) 这个条件扔掉,
则三个数字总和为(sum)的情况有(frac{(n - 1) imes (n - 2)}{2})
然后减去有(1/2/3)个数字(x > n) 的情况
首先是(3)个数都大于(n) 那直接先默认给(3)个位置加上(n), 即现在数字和为(sum - 3 imes n)
即(frac{(n - 1 - 3 imes n) imes (n - 2 - 3 imes n)}{2})
然后我们默认给位置(1(2, 3))加上(n), 当前总和为(sum - n)
(注意, (sum leqslant 3 imes n) 即不存在 (sum - n geqslant 3 imes n) 的情况)
这一步我们做了(3)次, 因为有三个位置, 其中位置((1, 2), (2, 3), (1, 3)) 会算重一次有 (2) 个数大于 (n) 的
所以我们还要加上(3)次有两个位置数大于(n) 的, 即(sum - 2 imes n), (frac{(n - 1 - 2 imes n) imes (n - 2 - 2 imes n)}{2})
找到了所求的3个数的数位和, 剩下的就好求了,
逐一确定位置(1, 2, 3)为几即可, 保证(1 leqslant x leqslant n) 即可
ll calc(ll x) { return x < 3 ? 0 : (x - 1) * (x - 2) >> 1; }
ll work(ll x) { return calc(x) - calc(x - 3 * n) - 3 * calc(x - n) + 3 * calc(x - 2 * n); }
int main() {
IOS; ll k, s; cin >> n >> k; s = work(m = 3);
while (s < k) k -= s, s = work(++m);
rep (i, max(m - 2 * n, 1), n) {
s = min(n, m - i - 1) - max(m - n - i, 1) + 1;
if (k > s) { k -= s; continue; }
return cout << i << ' ' << max(m - n - i, 1) + k - 1 << ' ' << m - i - max(m - n - i, 1) - k + 1, 0;
}
return 0;
}
F - Minflip Summation
比较抽象, 我们先来考虑(K = 1), 字符串不含(?)
当(s[i] != s[i + 1]) 则必定要反转([l, i]) 或 ([i + 1, r])
对于(s[n - 1] != s[0]) 则必定反转([0, l]) 或([n - 1, n - 1])
故把字符串当成环, 没出现一次(s[i] != s[i + 1]) 就要反转(0.5)次
对于(s[i] = ?) 则会出现 (s[i] == s[i + 1]) 或 (s[i] != s[i + 1]) 那不就是反转(0.25)次吗?
故我们得到了(K = 1) 情况下的(T')答案sum,
一共有(2^{KQ})种字符串, 有(K)段字符串(S), 故答案为
(2^{KQ} imes K imes sum)
ll k, qp, sum, q, ans;
string s;
ll qpow(ll a, ll b) {
ll ans = 1;
for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
return ans;
}
int f(char x,char y) { return x == '?' || y == '?' ? qp : x != y; }
int main(){
cin >> s >> k; qp = qpow(2, mod - 2);
if (s.size() * k == 1) return cout << 0, 0;
rep (i, 0, s.size() - 1) sum = (sum + f(s[i], s[(i + 1) % s.size()])) % mod, q += s[i] == '?';
ll ans = qpow(2, k * q) * k % mod * sum % mod * qp % mod;
cout << ans;
return 0;
}