P2351 [SDOI2012]吊灯

P2351 SDOI2012吊灯

对于能够分成大小为 \(i\) 的若干个联通块,要求至少 \(\lfloor \frac{N}{i} \rfloor\) 个节点子树的 \(size\)\(i\) 的倍数。

这是显然的。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

typedef long long ll;
const ll MAXN = 1.2e6+10, D = 19940105;

ll N, M, fa[MAXN], siz[MAXN], sq[MAXN];
vector <ll> q;

int main() {
    ios::sync_with_stdio(false);
    cin >> N;
    for (ll i = 1; i * i <= N; i++) {
        if (N % i) continue;
        ll tem = N / i;
        if (tem != i) {
            q.push_back(tem);
        }
        q.push_back(i);
    }
    sort(q.begin(), q.end());
    for (ll k = 1; k <= 10; k++) {
        cout << "Case #" << k << ":\n";
        siz[1] = 1;sq[1] = 0;
        for (ll j = 2; j <= N; j++) {
            siz[j] = 1; sq[j] = 0;
            if (k == 1) {
                if (j != 2) cin.get();
                cin >> fa[j];
            } else fa[j] = (fa[j] + D) % (j - 1) + 1;
        }
        for (ll i = N; i > 1; i--) {
            siz[fa[i]] += siz[i];
            sq[siz[i]]++;
        }
        sq[siz[1]]++;
        for (unsigned int i = 0; i < q.size(); i++) {
            ll ret = 0, now = q.at(i);
            for (ll j = 1; now*j <= N; j++) ret += sq[now*j];
            if (ret * now >= N) cout << now << '\n';
        }
    }
    return 0;
}
posted @ 2020-09-25 19:51  Gensokyo_Alice  阅读(84)  评论(1编辑  收藏  举报