@xiaoziyao
2020-10-22T23:40:56.000000Z
字数 2386
阅读 1142
未分类
CF1228E Another Filling the Grid解题报告:
容斥又不会做,就是反演这种东西,才能维持的了生活。
首先,因为要使每行每列最小值为,所以每一行都要有。
正难则反,我们不能很快地计算行列每一行列都有,可以尝试设表示矩阵中恰好行列全部没有,表示矩阵中有行列全部没有。
很容易计算,设,则有
根据的定义,很显然有:
对于上面的式子,我们可以使用二项式反演来得到另一个式子:
最后,我们的答案就是了。
具体地,我们可以首先预处理逆元,然后求数组,然后通过带入上式得到,直接计算就好了。
复杂度:。
#include<stdio.h>
#define int long long
const int maxn=2005,mod=1000000007;
int n,k,ans;
int fac[maxn],nfac[maxn],g[maxn][maxn],f[maxn][maxn],amul[maxn*maxn],bmul[maxn*maxn];
inline int c(int n,int m){
return fac[n]*nfac[n-m]%mod*nfac[m]%mod;
}
int ksm(int a,int b){
int res=1;
while(b){
if(b&1)
res=res*a%mod;
a=a*a%mod,b>>=1;
}
return res;
}
signed main(){
fac[0]=1;
for(int i=1;i<maxn;i++)
fac[i]=fac[i-1]*i%mod;
nfac[maxn-1]=ksm(fac[maxn-1],mod-2);
for(int i=maxn-1;i>=1;i--)
nfac[i-1]=nfac[i]*i%mod;
scanf("%lld%lld",&n,&k);
amul[0]=bmul[0]=1;
for(int i=1;i<=n*n;i++)
amul[i]=amul[i-1]*(k-1)%mod,bmul[i]=bmul[i-1]*k%mod;
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++){
g[i][j]=c(n,i)*c(n,j)%mod*amul[n*n-(n-i)*(n-j)]%mod*bmul[(n-i)*(n-j)]%mod;
}
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++){
if((i+j)%2==0)
ans=(ans+g[i][j])%mod;
else ans=(ans-g[i][j]+mod)%mod;
}
printf("%lld\n",(ans+mod)%mod);
return 0;
}
二维二项式反演证明(这里式子不太一样,但原理差不多,懒得改了):
设,,那么由上式得:
然后由二项式反演得:
展开有:
再设,,那么代入上式有:
然后继续二项式反演:
展开有:
然后整理一下就有上面的式子了: