社区讨论

64pts求调

P14254分割(divide)参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mhj135zk
此快照首次捕获于
2025/11/03 18:59
4 个月前
此快照最后确认于
2025/11/03 18:59
4 个月前
查看原帖
下面的代码尝试枚举深度 ii,对深度为 ii 的点按照子树深度从大到小排序,然后组合数学计算,但部分测试点 WA
CPP
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+1;
const ll mod = 998244353;
int n, k, p[N], h[N], d[N];
ll ans, inv[N], fact[N], facinv[N];
vector<int> e[N], f[N];
void dfs(int u){
    h[u] = d[u];
    for(auto v:e[u]){
        d[v] = d[u] + 1;
        dfs(v);
        h[u] = max(h[u], h[v]);
    }
    f[d[u]].push_back(h[u]);
}
ll P(ll n, ll m){
    if (n<0 || n<m) return 0;
    return fact[n] * facinv[n-m] % mod;
}

int main(){
    inv[1] = fact[0] = facinv[0] = 1;
    for(ll i=2;i<N;i++) inv[i] = (mod-mod/i) * inv[mod%i] % mod;
    for(ll i=1;i<N;i++){
        fact[i] = fact[i-1] * i % mod;
        facinv[i] = facinv[i-1] * inv[i] % mod;
    }
    cin>>n>>k;
    for(int i=2;i<=n;i++){
        cin>>p[i];
        e[p[i]].push_back(i);
    }
    d[1] = 1;
    dfs(1);
    for(int i=1;i<=n;i++){
        int sz = f[i].size();
        if (sz <= k) continue;
        sort(f[i].begin(), f[i].end(), greater<int>());
        for(int r=0,l=0;r<sz;r++){
            if (r+1==sz||f[i][r+1]!=f[i][r]){
                if (r>=k){
                    ans += (P(r, k-1) - P(l, k-1) + mod) % mod * (r-l+1) % mod;
                    ans %= mod;
                    //cout << l <<' ' << r << ' '<<(P(r, k-1) - P(l, k-1) + mod) % mod * (r-l+1) % mod<<'\n';
                }
                if (l==k-1){
                    ans += fact[l] * (r-l+1) % mod;
                    ans %= mod;
                }
                l = r+1;
            }
        }
        //cout << i << ' ' << ans << '\n';
    }
    cout << ans;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...