习题:Another Filling the Grid(容斥)

题目

传送门

思路

考虑至少\(i\)行$ j$列的最小值不是\(1\)

那么此部分的方案总数为\(C_n^iC_n^j(k-1)^{in+jn-ij}\)
然后其他的部分即为\(k^{n^2+ij-in-jn}\)

同时配上一个容斥系数\((-1)^{i+j}\)

容斥系数这里可以打表找规律

具体的求容斥系数可以参照一道例题

然后此时已经可以过了,但是我们有更好的方法

\[\begin{aligned}&\sum_{i=0}^{n}\sum_{j=0}^{n}(-1)^{i+j}C_n^iC_n^j(k-1)^{in+jn-ij}k^{n^2+ij-in-jn}\\=&\sum_{i=0}^{n}\sum_{j=0}^{n}(-1)^{i+j}C_n^iC_n^j(k-1)^{i(n-j)}(k-1)^{jn}k^{(n-i)(n-j)}\\=&\sum_{i=0}^{n}\sum_{j=0}^{n}(-1)^{i+j}C_n^iC_n^j((k-1)^ik^{n-i})^{n-j}((k-1)^n)^j\\=&\sum_{i=0}^n(-1)^iC_n^i\sum_{j=0}^{n}(-1)^jC_n^j((k-1)^ik^{n-i})^{n-j}((k-1)^n)^j\\=&\sum_{i=0}^n(-1)^iC_n^i((k-1)^ik^{n-i}-(k-1)^n)^n(二项式定理)\end{aligned} \]

然后就可以从\(O(n^2)\)转换到\(O(nlog_n)\)

代码

#include<iostream>
#include<cstdio>
using namespace std;
const int mod=1e9+7;
int n,k;
long long qkpow(long long a,long long b)
{
    if(b==0)
        return 1;
    if(b==1)
        return a;
    long long t=qkpow(a,b/2);
    t=t*t%mod;
    if(b&1)
        t=t*a%mod;
    return t;
}
long long ans;
long long fac[255],inv[255];
long long C(int n,int m)
{
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
void prepa()
{
    fac[0]=1;
    for(int i=1;i<=n;i++)
        fac[i]=fac[i-1]*i%mod;
    inv[n]=qkpow(fac[n],mod-2);
    for(int i=n-1;i>=0;i--)
        inv[i]=inv[i+1]*(i+1)%mod;
}
int main()
{
    cin>>n>>k;
    //ans=qkpow(k,n*n);
    prepa();    
    for(int i=0;i<=n;i++)
    {
        long long a,b;
        a=qkpow(k-1,i)*qkpow(k,n-i)%mod;
        b=qkpow(k-1,n);
        a=((a-b)%mod+mod)%mod;
        a=((i&1)?-1:1)*C(n,i)*qkpow(a,n)%mod;
        //cout<<i<<" "<<a<<'\n';
        ans=((ans+a)%mod+mod)%mod;
    }
    cout<<ans;
    return 0;
}
posted @ 2020-12-22 21:46  loney_s  阅读(89)  评论(0)    收藏  举报