BZOJ 4487 [Jsoi2015] 染色问题

来源:互联网 发布:xmind mac 激活码 编辑:程序博客网 时间:2024/05/22 02:23

Description

棋盘是一个n×m的矩形,分成n行m列共n*m个小方格。现在萌萌和南南有C种不同颜色的颜料,他们希望把棋盘用这些颜料染色,并满足以下规定:
1.  棋盘的每一个小方格既可以染色(染成C种颜色中的一种) ,也可以不染色。
2.  棋盘的每一行至少有一个小方格被染色。
3.  棋盘的每一列至少有一个小方格被染色。
4.  种颜色都在棋盘上出现至少一次。
以下是一些将3×3棋盘染成C = 3种颜色(红、黄、蓝)的例子:

请你求出满足要求的不同的染色方案总数。只要存在一个位置的颜色不同,
即认为两个染色方案是不同的

Input

输入只有一行 3 个整数n,m,c。1 < = n,m,c < = 400

Output

输出一个整数,为不同染色方案总数。因为总数可能很大,只需输出总数
mod 1,000,000,007的值。

Sample Input

2 2 3

Sample Output

60

HINT

Source

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

数论+思路~

设有i行j列k颜色是可能存在的,那么此时的种类数为0<=i<=n,0<=j<=m,0<=k<=c,c[i][n]*c[j][m]*c[k][c]*(k+1)^(i*j)*(-1)^(n+m+c-i-j-K)。

这样O(nmc)的算法据说可以卡过……但是我被卡常了……

我们将有j的项提取出来,得到0<=i<=n,0<=j<=m,0<=k<=c,(-1)^(n+m+c-i-K)*c[i][n] * c[k][c] * ((k+1)^i)^j * c[j][m]*(-1)^(-j),

注意到后面包含j的项刚好是(1-k)^n的展开的形式。

所以原式可化简为0<=i<=n,0<=k<=c,(-1)^(n+m+c-i-K)*c[i][n] * c[k][c] *(1-(k+1)^i)^m。

另:取模这个东西真是莫名其妙……WA了半天结果是先乘了-1^k后取模……所以遇到这种情况要先取模再乘啊……


被卡常的代码:

#include<cstdio>#define ll long long#define modd 100000007int n,m,cc,c[401][401],ans;int read(){int x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}int mi(int u,int v){int now=1;u%=modd;while(v){if(v&1) now=(ll)now*u%modd;u=(ll)u*u%modd;v>>=1;}return now;}int main(){n=read();m=read();cc=read();c[0][0]=1;for(int i=1;i<=400;i++){c[i][0]=1;for(int j=1;j<=400;j++) c[i][j]=(ll)(c[i-1][j]+c[i-1][j-1])%modd;}for(int i=0;i<=n;i++)  for(int j=0;j<=m;j++)for(int k=0;k<=cc;k++) ans=((ll)ans+(ll)mi(-1,n+m+cc-i-j-k)*c[n][i]*c[m][j]*c[cc][k]*mi(k+1,i*j))%modd;printf("%d\n",ans);return 0;}


A了的代码:

#include<cstdio>#define ll long long#define modd 1000000007int n,m,cc;ll c[401][401],ans;int read(){int x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}ll mi(ll u,ll v){ll now=1;u%=modd;while(v){if(v&1) now=now*u%modd;u=u*u%modd;v>>=1;}return now;}ll kk(ll u){return u&1 ? modd-1:1;}int main(){n=read();m=read();cc=read();c[0][0]=1;for(int i=1;i<=400;i++){c[i][0]=1;for(int j=1;j<=400;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%modd;}for(int i=0;i<=n;i++)  for(int k=0;k<=cc;k++)  {  ll now=(c[n][i]*c[cc][k]%modd)*kk(n^m^cc^i^k)%modd;  now=now*mi((1-mi(k+1,i)+modd)%modd,m)%modd;  ans=(ans+now)%modd;  }printf("%lld\n",ans);return 0;}



原创粉丝点击