【JSOI2015】bzoj4487 染色问题

来源:互联网 发布:淘宝账号怎么注册不了 编辑:程序博客网 时间:2024/05/05 23:37

考虑容斥,即枚举没有涂色的行、列和没有用的颜色。答案是

i=0nj=0mk=0c(1)i+j+k(ni)(mj)(ck)(ck+1)(ni)(mj)

复杂度是O(nmc),但是我们还可以进一步优化。把所有关于m的项提出来,我们得到
i=0mk=0c(1)i+k(ni)(ck)j=0m(nj)[(ck+1)ni]mj(1)j

根据二项式定理,右边一部分就是
[(ck+1)ni1]m

这样复杂度就是O(min(n,m)clogmax(n,m))

#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int p=1000000007,maxn=410;int n,m,c,C[maxn][maxn];int pow(int base,int k){    int ret=1;    for (;k;k>>=1,base=(LL)base*base%p)        if (k&1) ret=(LL)ret*base%p;    return ret;}int inc(int x,int y){    x+=y;    return x>=p?x-p:x;}int dec(int x,int y){    x-=y;    return x<0?x+p:x;}int main(){    int ans=0,mx;    scanf("%d%d%d",&n,&m,&c);    mx=max(n,c);    for (int i=0;i<=mx;i++) C[i][0]=1;    for (int i=0;i<=mx;i++)        for (int j=1;j<=i;j++)            C[i][j]=inc(C[i-1][j],C[i-1][j-1]);    for (int i=0;i<=n;i++)        for (int k=0;k<=c;k++)            if (i+k&1) ans=dec(ans,(LL)C[n][i]*C[c][k]%p*pow(dec(pow(c-k+1,n-i),1),m)%p);            else ans=inc(ans,(LL)C[n][i]*C[c][k]%p*pow(dec(pow(c-k+1,n-i),1),m)%p);    printf("%d\n",ans);}