CF232B Table

2023-08-07 16:29:49

题意

有一个 n×m的矩阵,求使得每个 n×n的矩阵中都有正好 k个点的方案数,方案数对 1e9+7 取模。 1n100,nm1018,0kn2

思路

通过观察样例并且自己手玩了一些数据后,我们发现,假设第 i 列放了 k 个数,那么如果 i+rn 列想做到前 n 列的点数和与 i 列前 n 列点数和相同,那么也得放 k 个。

所以我们只需要处理前 n 的情况就能推广到 m 列的情况了。只需要把这些相同的方案相乘即可,具体就是算取的时候带个指数吧。

转移很好想,令 fi,k 表示前 i 列有 k 个点的方案数,x 表示 i 列放了 x 个点。那么有转移:

fi,k=x=0min(k,n)fi1,kx×(nx)m/n+(mmodni)

O(n2log)预处理 (nx)m/n+(mmodni),然后 O(n2K) 转移,空间复杂度 O(nK),也可以滚到 O(K)

Code

ll n,m,K,fac[105],ifac[105],f[105][10005],cnt[105][105];
ll qpow(ll x,ll w){
ll res=1;
for(;w;w>>=1,x=x*x%mod)if(w&1)res=res*x%mod;
return res;
}
ll C(ll x,ll y){
return (fac[x]%mod*ifac[y]%mod)%mod*ifac[x-y]%mod;
}
int main(){
cin>>n>>m>>K;
fac[0]=1;
for(ll i=1;i<=n;i++){
fac[i]=fac[i-1]*i%mod;
cnt[n+1][i]=(m/n+(m%n>=i))%(mod-1);
}
ifac[n]=qpow(fac[n],mod-2);
for(ll i=n-1;~i;--i){
ifac[i]=ifac[i+1]*(i+1)%mod;
}
for(ll i=0;i<=n;i++)
for(ll j=1;j<=n;j++)
cnt[i][j]=qpow(C(n,i),cnt[n+1][j]);
f[0][0]=1;
for(ll i=1;i<=n;i++)
for(ll k=0;k<=K;k++)
for(ll x=0;x<=min(n,k);x++){
f[i][k]=(f[i][k]+f[i-1][k-x]*cnt[x][i]%mod)%mod;
}
cout<<f[n][K];
}

本文作者:NBestの思潮

本文链接:https://www.cnblogs.com/NBest/p/17686919.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   NBest  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起