【BZOJ4487】【JSOI2015】染色问题

题意:

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


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

$1\leq n,m,c\leq 400$

题解:

这题。。。$O(nmc)$能过。。。没啥好说的

$ans=\sum\limits_{i=0}^{n}\sum\limits_{j=0}^{m}\sum\limits_{k=0}^{c}(-1)^{i+j+k}\binom{n}{i}\binom{m}{j}\binom{c}{k}(c-k+1)^{(n-i)(m-j)}$

没了。

代码:

 1 //O(nmc) dafa good!
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<queue>
 8 #define inf 2147483647
 9 #define eps 1e-9
10 #define mod 1000000007
11 using namespace std;
12 typedef long long ll;
13 int n,m,c,ans=0,C[401][401];
14 int fastpow(int x,int y){
15     int ret=1;
16     for(;y;y>>=1,x=(ll)x*x%mod){
17         if(y&1)ret=(ll)ret*x%mod;
18     }
19     return ret;
20 }
21 void add(int &a,int b){
22     if(a+b>mod)a=a-mod+b;
23     else a=a+b;
24 }
25 void dec(int &a,int b){
26     if(a-b<0)a=a-b+mod;
27     else a=a-b;
28 }
29 int main(){
30     //freopen("in.txt","r",stdin);
31     C[1][0]=C[1][1]=1;
32     for(int i=2;i<=400;i++){
33         C[i][0]=1;
34         for(int j=1;j<=i;j++){
35             C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
36         }
37     }
38     scanf("%d%d%d",&n,&m,&c);
39     for(int k=0;k<=c;k++){
40         int t3=1,s=c-k+1;
41         for(int i=n;i>=0;i--){
42             int t2=1;
43             for(int j=m;j>=0;j--){
44                 int t1=(ll)C[n][i]*C[m][j]%mod*C[c][k]%mod;
45                 //int t2=fastpow(c-k+1,(n-i)*(m-j));
46                 t1=(ll)t1*t2%mod;
47                 if((i+j+k)&1)ans=(ans-t1+mod)%mod;//dec(ans,t1);
48                 else ans=(ans+t1)%mod;//add(ans,t1);
49                 t2=(ll)t2*t3%mod;
50             }
51             t3=(ll)t3*s%mod;
52         }
53     }
54     printf("%d",ans);
55     return 0;
56 }
posted @ 2018-09-14 19:49  DCDCBigBig  阅读(436)  评论(0编辑  收藏  举报