【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 }