CodeCraft-21 and Codeforces Round #711 (Div. 2)

CodeCraft-21 and Codeforces Round #711 (Div. 2)

A - GCD Sum

int main() {
    IOS;
    for (cin >> _; _; --_) {
        ll n; cin >> n;
        while (1) {
            ll c = n, g = 0;
            while (c) g += c % 10, c /= 10;
            if (__gcd(n, g) > 1) break; ++n;
        }
        cout << n << '\n';
    }
    return 0;
}

B - Box Fitting

B 就考二分, 我是没想到

贪心想, 肯定是先放长的物品, 且尽量不浪费每一层的空间

长度都是二进制, 那就拆位放呗

再套一个二分需要多少层

int a[30];
map<int, int> lg;
 
bool check(int mid) {
    for (ll i = 29, j = 0; ~i; j -= a[i--]) {
        j = (m >> i & 1) * mid + j * 2;
        if (j < a[i]) return 0;
    }
    return 1;
}
 
int main() {
    IOS; rep (i, 0, 29) lg[1 << i] = i;
    for (cin >> _; _; --_) {
        cin >> n >> m; memset(a, 0, sizeof a);
        rep (i, 1, n) cin >> k, ++a[lg[k]];
        int l = 1, r = n;
        while (l < r) {
            int mid = l + r >> 1;
            if (check(mid)) r = mid;
            else l = mid + 1;
        }
        cout << l << '\n';
    }
    return 0;
}

C - Planar Reflections

来回前缀和就行了, 比如(min(n, m) > 1)最开始

我们直接预处理, 让每个隔板之间有一个 \((m - 1)\) 的粒子且这些粒子都向右

则当前倒序和为 \(a[1] = m - 1, a[2] = m - 2, ... a[m - 1] = 1\)

则最终会在第一个隔板的左边有 a[1] 个 \(m - 1\) 粒子

再隔板\(i + 1\)\(i\) 之间有 \(a[i]\)\(m - 2\) 粒子, 且向左, 又变成了前缀和

模拟就行了

ll c[N], ans;
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> m;
        if (m == 1) { cout << "1\n"; continue; }
        if (n == 1) { cout << "2\n"; continue; }
        rep (i, 2, n + 1) c[i] = 0; ans = 2;
        per (i, n, 2) c[i] = c[i + 1] + 1;
        rep (i, 2, m) {
            ans = (ans + (i & 1 ? c[n] : c[2])) % mod;
            if (i & 1) per (j, n, 2) c[j] = (c[j] + c[j + 1]) % mod;
            else rep (j, 2, n) c[j] = (c[j] + c[j - 1]) % mod;
        }
        cout << (ans + mod) % mod << '\n';
    }
    return 0;
}

D - Bananas in a Microwave

分组背包, 而且还只讨论可行性, 怎么写都行

int main() {
    IOS; cin >> n >> m; memset(v, -1, sizeof v); v[0] = 0;
    rep (i, 1, n) {
        ll x, y; cin >> _ >> x >> y;
        rep (j, 0, m) if (~v[j] && v[j] ^ i) {
            ll c = j;
            rep (k, 1, y) {
                c = _ == 1 ? ceil((c * 1e5 + x) / 1e5) : ceil(c * x / 1e5);
                if (c <= m && !(~v[c])) v[c] = i;
                else break;
            }
        }
    }
    rep(i, 1, m) cout << v[i] << ' ';
    return 0;
}

E - Two Houses

贪心的从贡献大到那个贡献小问就行, 怎么问呢?

当然是问入度大的点\(x\) 连不连接 入度小的点\(y\)

假设连接\(x\)的点集为\(S_x\), 连接\(y\)的点集为\(S_y\)

已知 \(SIZE(S_y) \leqslant SIZE(S_x)\) 则必定存在一个点 \(z\)

\(z\)属于\(S_x\)而不属于\(S_y\), 即\(z\)连向\(x\), \(y\)连向\(z\), 如果询问得到\(x\)连向\(y\), 环就已将出来了

int a[N];
PII b[N * N];
 
int main() {
    IOS; cin >> n; rep (i, 1, n) cin >> a[i];
    rep (i, 1, n) rep (j, i + 1, n) b[++m] = a[i] < a[j] ? PII{ j, i } :  PII{ i, j };
    sort(b + 1, b + 1 + m, [&](PII &x, PII &y) { return a[x.fi] - a[x.se] > a[y.fi] - a[y.se]; });
    rep (i, 1, m) {
        cout << "? " << b[i].fi << ' ' << b[i].se << endl;
        string s; cin >> s;
        if (s[0] == 'Y') return cout << "! " << b[i].fi << ' ' << b[i].se, 0;
    }
    return cout << "! 0 0", 0;
}
posted @ 2021-04-02 20:30  洛绫璃  阅读(110)  评论(0编辑  收藏  举报