KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)

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\n" << g[s].size();
        for (auto &j : g[s]) cout << ' ' << j;
        cout << '\n' << 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) \times (n - 2)}{2}\)

然后减去有\(1/2/3\)个数字\(x > n\) 的情况

首先是\(3\)个数都大于\(n\) 那直接先默认给\(3\)个位置加上\(n\), 即现在数字和为\(sum - 3 \times n\)

\(\frac{(n - 1 - 3 \times n) \times (n - 2 - 3 \times n)}{2}\)

然后我们默认给位置\(1(2, 3)\)加上\(n\), 当前总和为\(sum - n\)

(注意, \(sum \leqslant 3 \times n\) 即不存在 \(sum - n \geqslant 3 \times n\) 的情况)

这一步我们做了\(3\)次, 因为有三个位置, 其中位置\((1, 2), (2, 3), (1, 3)\) 会算重一次有 \(2\) 个数大于 \(n\)

所以我们还要加上\(3\)次有两个位置数大于\(n\) 的, 即\(sum - 2 \times n\), \(\frac{(n - 1 - 2 \times n) \times (n - 2 - 2 \times 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} \times K \times 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;
}
posted @ 2021-05-09 15:53  洛绫璃  阅读(238)  评论(1编辑  收藏  举报