[关闭]
@xiaoziyao 2020-10-22T15:40:56.000000Z 字数 2386 阅读 976

CF1228E Another Filling the Grid

未分类


CF1228E Another Filling the Grid解题报告:

更好的阅读体验

题意

分析

容斥又不会做,就是反演这种东西,才能维持的了生活。

首先,因为要使每行每列最小值为,所以每一行都要有

正难则反,我们不能很快地计算列每一行列都有,可以尝试设表示矩阵中恰好列全部没有表示矩阵中有列全部没有

很容易计算,设,则有

根据的定义,很显然有:

对于上面的式子,我们可以使用二项式反演来得到另一个式子:

最后,我们的答案就是了。

具体地,我们可以首先预处理逆元,然后数组,然后通过带入上式得到,直接计算就好了。

复杂度:

代码

  1. #include<stdio.h>
  2. #define int long long
  3. const int maxn=2005,mod=1000000007;
  4. int n,k,ans;
  5. int fac[maxn],nfac[maxn],g[maxn][maxn],f[maxn][maxn],amul[maxn*maxn],bmul[maxn*maxn];
  6. inline int c(int n,int m){
  7. return fac[n]*nfac[n-m]%mod*nfac[m]%mod;
  8. }
  9. int ksm(int a,int b){
  10. int res=1;
  11. while(b){
  12. if(b&1)
  13. res=res*a%mod;
  14. a=a*a%mod,b>>=1;
  15. }
  16. return res;
  17. }
  18. signed main(){
  19. fac[0]=1;
  20. for(int i=1;i<maxn;i++)
  21. fac[i]=fac[i-1]*i%mod;
  22. nfac[maxn-1]=ksm(fac[maxn-1],mod-2);
  23. for(int i=maxn-1;i>=1;i--)
  24. nfac[i-1]=nfac[i]*i%mod;
  25. scanf("%lld%lld",&n,&k);
  26. amul[0]=bmul[0]=1;
  27. for(int i=1;i<=n*n;i++)
  28. amul[i]=amul[i-1]*(k-1)%mod,bmul[i]=bmul[i-1]*k%mod;
  29. for(int i=0;i<=n;i++)
  30. for(int j=0;j<=n;j++){
  31. g[i][j]=c(n,i)*c(n,j)%mod*amul[n*n-(n-i)*(n-j)]%mod*bmul[(n-i)*(n-j)]%mod;
  32. }
  33. for(int i=0;i<=n;i++)
  34. for(int j=0;j<=n;j++){
  35. if((i+j)%2==0)
  36. ans=(ans+g[i][j])%mod;
  37. else ans=(ans-g[i][j]+mod)%mod;
  38. }
  39. printf("%lld\n",(ans+mod)%mod);
  40. return 0;
  41. }

二项式反演证明

二维二项式反演证明(这里式子不太一样,但原理差不多,懒得改了):

,那么由上式得:

然后由二项式反演得:

展开有:

再设,那么代入上式有:

然后继续二项式反演:

展开有:

然后整理一下就有上面的式子了:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注