题解:AT_wtf22_day2_d Cat Jumps
nullqtr_pwp · · 题解
第三次被模拟赛考了忍不了了来发一篇。
将所有正的互相区分,最后再乘
钦定若干位置形成前缀和为
这样形成内向基环树森林,算出有
将环边边权拆为
时间复杂度
int n,a[maxn],ifac[maxn],fac[maxn];
int S2[maxn][maxn],S1[maxn][maxn],C[maxn][maxn];
void init(){
const int N=5000;
fac[0]=ifac[0]=1;
F(i,1,N)fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=qpow(fac[i],mod-2);
S1[0][0]=S2[0][0]=1;
F(i,0,N)C[i][0]=1;
F(i,1,N)F(j,1,i)C[i][j]=add(C[i-1][j-1],C[i-1][j]);
F(i,1,N)F(j,1,i)S1[i][j]=add(S1[i-1][j-1],1ll*(i-1)*S1[i-1][j]%mod);
F(i,1,N)F(j,1,i)S2[i][j]=add(S2[i-1][j-1],1ll*j*S2[i-1][j]%mod);
}
int dp[maxn][maxn];
int ans[maxn],vis[maxn],f[maxn],sum,F[maxn];
void solve(){
cin>>n,init();
F(i,1,n)cin>>a[i],inc(sum,a[i]);
dp[0][0]=1;
F(i,1,n)F(j,0,i-1){
const int val=dp[i-1][j];if(!val)continue;
inc(dp[i][j+1],1ll*val*(a[i]+1)%mod);
inc(dp[i][j],1ll*val*(sum+i-j)%mod);
}
F(i,0,n)F(j,0,i)inc(f[j],1ll*dp[n][i]*S1[i][j]%mod);
dF(i,n,1)F(j,i+1,n)dec(f[i],1ll*f[j]*C[j][i]%mod);
F(i,1,n)F(j,1,i)inc(F[j],1ll*f[i]*S2[i][j]%mod);
dF(i,n,1){
ans[i]=1ll*F[i]*fac[i]%mod;
F(j,i+1,n)dec(ans[i],1ll*C[j-1][i-1]*ans[j]%mod);
}
int coef=1;
F(i,1,n)++vis[a[i]];
F(i,1,n)coef=1ll*ifac[vis[a[i]]]*coef%mod,vis[a[i]]=0;
F(i,1,n)ans[i]=1ll*ans[i]*coef%mod;
F(i,1,n)cout<<ans[i]<<' ';cout<<'\n';
}