codeforces#1228E. Another Filling the Grid(容斥定理,思维)
题目链接:
https://codeforces.com/contest/1228/problem/E
题意:
给n*n的矩阵填数,使得每行和每列最小值都是1
矩阵中可以填1到$k$的数
数据范围:
$1\leq n \leq 250$
$1\leq k \leq 250$
分析:
参考博客:https://www.cnblogs.com/scx2015noip-as-php/p/cf589e.html
先预处理出f(x)代表x*n的矩阵,每列最小值是1的填充方案数
以下讨论的方案数,列的最小值一定是1
ans=随便填-第一行没有1-第二行没有1-第三行没有1-第n行没有1+第一二行没有1+第二三行没有1......
也就是对行的方案容斥
因为第一行没有1和第二行没有1的方案可能重复了,所有多减了一些方案数
$ans = \sum\limits_{i=0}^n (-1)^i C_n^i (k-1)^{ni} f(n-i)$
AC代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=250+7; const int mod=1e9+7; ll A[maxn],invA[maxn],f[maxn]; ll qpow(ll x,ll y){ ll res=1; while(y){ if(y&1)res=x*res%mod; x=x*x%mod; y/=2; } return res; } int main() { int n,k; A[1]=invA[1]=A[0]=invA[0]=1; for(int i=2;i<maxn;i++){ A[i]=A[i-1]*i%mod; invA[i]=invA[i-1]*qpow(i,mod-2)%mod; } scanf("%d %d",&n,&k); for(int i=1;i<=n;i++) f[i]=qpow((qpow(k,i)-qpow(k-1,i)+mod)%mod,n); ll res,ans=0; for(int i=0;i<n;i++){ if(i%2==0)res=1; else res=-1; res=res*f[n-i]; res=res*qpow(k-1,n*i)%mod; res=res*A[n]%mod*invA[i]%mod*invA[n-i]%mod; ans=(ans+res+mod)%mod; } printf("%lld\n",ans); return 0; }