标签:需要 main play rac tps while lan turn 强制
如果令 \(G(i)\) 表示恰好有 \(i\) 种颜色出现了 \(S\) 次,答案就是
令 \(lim=min(n/s,m)\),我们只需要求出 \(0\) ~ \(lim\) 的 \(G\)。
容易想到令 \(F(i)\) 表示强制令 \(i\) 种颜色出现了 \(s\) 次,剩下的随便选的可重方案,那么
可以发现,序列 \(F\) 能够直接 \(O(n \log n)\) 预处理出来。
又容易知道
再令 \(A(i)=\frac{(-1)^i}{i!}\) 和 \(B(i)=(lim-i)!F(lim-i)!\),即 \(B(lim-i)=i!F(i)\)。所以上式可以变成
容易发现这是卷积的形式。求出 \(A\) 和 \(B\) 的卷积多项式后,再把其 reverse 一下,就是 \(G\) 了。
复杂度 \(O(n\log n)\),其中 \(n\) 和上文的 \(lim\) 同阶。
#include<stdio.h>
#include<algorithm>
using namespace std;
#define ll long long
#define rint register int
const int V=10100007;
const int N=(1<<21)+3;
const int P=1004535809;
const int G=3;
inline ll qpow(ll x,ll y){
ll ret=1,cnt=0;
while(y>=(1ll<<cnt)){
if(y&(1ll<<cnt)) ret=ret*x%P;
x=x*x%P,cnt++;
}
return ret;
}
const int Gi=qpow(G,P-2);
inline int read(){
int x=0,flag=1; char c=getchar();
while(c<‘0‘||c>‘9‘){if(c==‘-‘) flag=0;c=getchar();}
while(c>=‘0‘&&c<=‘9‘){x=(x<<1)+(x<<3)+c-48;c=getchar();}
return flag? x:-x;
}
int rk[N],n,m,op,s;
ll a[N],b[N],w[N],fac[V],inv[V];
ll C(int x,int y){return x<y? 0:fac[x]*inv[y]%P*inv[x-y]%P;}
inline void swap(ll &x,ll &y){x^=y,y^=x,x^=y;}
inline void NTT(ll *F){
for(rint i=0;i<n;i++)
if(i<rk[i]) swap(F[i],F[rk[i]]);
for(rint p=2;p<=n;p<<=1){
int len=p>>1;
ll w=qpow(op? G:Gi,(P-1)/p);
for(rint k=0;k<n;k+=p){
ll now=1;
for(rint l=k;l<k+len;l++){
ll t=now*F[l+len]%P;
F[l+len]=(F[l]-t+P)%P;
F[l]=(F[l]+t)%P;
now=now*w%P;
}
}
}
}
inline int min(int x,int y){return x<y? x:y;}
int main(){
n=read(),m=read(),s=read();
for(rint i=0;i<=m;i++) w[i]=read();
int lim=min(m,n/s),M=max(n,m)+1;
fac[0]=1;
for(rint i=1;i<M;i++) fac[i]=fac[i-1]*i%P;
inv[M-1]=qpow(fac[M-1],P-2);
for(rint i=M-2;~i;i--) inv[i]=inv[i+1]*(i+1)%P;
for(rint i=0;i<=lim;i++)
a[lim-i]=fac[i]*C(m,i)%P*fac[n]%P*inv[n-s*i]%P*qpow(inv[s],i)%P*qpow(m-i,n-s*i)%P;
for(rint i=0,opt=1;i<=lim;i++,opt=-opt) b[i]=(opt*inv[i]+P)%P;
for(n=1;n<=(lim<<1);n<<=1);
for(rint i=0;i<n;i++)
rk[i]=(rk[i>>1]>>1)|((i&1)? n>>1:0);
op=1,NTT(a),NTT(b);
for(rint i=0;i<n;i++) a[i]=a[i]*b[i]%P;
op=0,NTT(a);
reverse(a,a+1+lim);
ll ans=0,Inv=qpow(n,P-2);
for(rint i=0;i<=lim;i++) ans=(ans+w[i]*a[i]%P*inv[i]%P*Inv%P)%P;
printf("%lld",ans);
}
标签:需要 main play rac tps while lan turn 强制
原文地址:https://www.cnblogs.com/wwlwQWQ/p/14360498.html