P4491 [HAOI2018] 染色
阿新 • • 發佈:2019-03-25
.org ever -- 多項式 rac max all lose print
題目鏈接
題意分析
要求\(k\)種顏色恰好出現\(S\)次
也就是出現\(S\)次的顏色恰好有\(k\)種
我們可以發現\(lim=max\{k\}=min(\frac{n}{s},{m})\)
我們可以容斥一下 就是
出現\(S\)次的顏色至少存在\(k\)種
那麽
\[dp[k]=C_m^kC_{n}^{ks}(m-k)^{m-ks}\]
應該和好理解的
出現\(S\)次的顏色恰好\(k\)種就是
\[ans[k]=\sum_{j=k}^{lim}(-1)^{j-k}C_j^kdp[j]\]
\(j\)種顏色中\(k\)種被重復算了\(C_j^k\)次
那麽我們拆開就是
\[ans[k]* k!=\sum_{j=k}^{lim}\frac{(-1)^{j-k}}{(j-k)!}dp[j]* j!\]
如何求\(\sum_{j=k}^{lim}\frac{(-1)^{j-k}}{(j-k)!}dp[j]* j!\)
我們考慮維護出
\[a[i]=dp[i]* i!\ \ \ \ \ \ b[i]=\frac{(-1)^{i}}{i!}\]
然後就是套路 翻轉\(a\)序列
那麽就是多項式乘法\(NTT\)了
那麽對應就是\(lim-j+j-k=lim-k\)
所以我們再反轉一下就可以了
然後累加就可以了
CODE:
/*-------------OI使我快樂-------------*/ int n,m,s,have,lim,all; ll ans; ll fav[M],fac[M],inv[M],num[M]; ll dp[M],cdy[M],wzy[M]; int key[M]; IL ll C(int x,int y) {return fac[x]*fav[x-y]%mod*fav[y]%mod;} IL ll qpow(ll x,ll y) {ll res=1;for(;y;y>>=1,x=x*x%mod) if(y&1) res=res*x%mod;return res;} IL void NTT(ll *A,int knd) { for(R int i=0;i<lim;++i) if(i<key[i]) swap(A[i],A[key[i]]); for(R int mid=1;mid<lim;mid<<=1) { ll Wn=qpow(knd==1 ? 3:Gi,(mod-1)/(mid<<1)); for(R int j=0;j<lim;j+=(mid<<1)) { ll w=1; for(R int k=0;k<mid;++k,w=w*Wn%mod) { ll x=A[j+k],y=w*A[j+k+mid]%mod; A[j+k]=(x+y)%mod;A[j+k+mid]=(x-y+mod)%mod; } } } if(knd==-1) { ll inv=qpow(lim,mod-2); for(R int i=0;i<lim;++i) A[i]=A[i]*inv%mod; } } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); read(n);read(m);read(s);have=min(n/s,m); for(R int i=0;i<=m;++i) read(num[i]),num[i]%=mod; fac[0]=fac[1]=fav[0]=fav[1]=inv[0]=inv[1]=1; for(R int i=2;i<=10000000;++i) { fac[i]=fac[i-1]*i%mod; inv[i]=(mod-mod/i)*inv[mod%i]%mod; fav[i]=fav[i-1]*inv[i]%mod; } // for(R ll i=1;i<=10;++i) printf("%lld%c",fac[i],(i==10 ? '\n':' ')); for(R int i=0;i<=have;++i) dp[i]=C(m,i)*C(n,i*s)%mod*fac[i*s]%mod*qpow(fav[s],i)%mod*qpow(m-i,n-i*s)%mod; // for(R ll i=0;i<=have;++i) // printf("%lld%c",dp[i],(i==have ? '\n':' ')); for(R int i=0;i<=have;++i) { cdy[i]=(((i&1) ? -1:1)*fav[i]%mod+mod)%mod; wzy[i]=dp[i]*fac[i]%mod; } reverse(wzy,wzy+have+1); for(lim=1;lim<=(have<<1);lim<<=1) ++all; for(R int i=0;i<lim;++i) key[i]=((key[i>>1]>>1)|((i&1)<<(all-1))); NTT(cdy,1);NTT(wzy,1); for(R int i=0;i<lim;++i) cdy[i]=cdy[i]*wzy[i]%mod; NTT(cdy,-1); reverse(cdy,cdy+have+1); for(R int i=0;i<=have;++i) ans=(ans+num[i]*cdy[i]%mod*fav[i]%mod)%mod; printf("%lld\n",(ans%mod+mod)%mod); // fclose(stdin); // fclose(stdout); return 0; }
HEOI 2019 RP++
P4491 [HAOI2018] 染色