P3158 [CQOI2011]放棋子
P3158 [CQOI2011]放棋子
本蒟蒻表示把有趣恶心。。。
因为不同颜色的棋子不能在同一行或者同一列,所以每种颜色的棋子的摆放是相对独立的。
于是考虑设计这么一个状态
其它都好处理,但“用
考虑再设一个状态
则
我们预处理
不一定要每行每列都占领,但棋子要全放完,答案就为:
时间复杂度
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define MAXN 40
#define MAXM 20
#define MAXK 910
#define MOD 1000000009LL
using namespace std;
int n,m,c,S;
long long ans=0;
long long g[MAXN][MAXN],triangle[MAXK][MAXK],dp[MAXN][MAXN][MAXM];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
void work(){
int u,v,w;
for(int k=1;k<=c;k++){
int w=read();
memset(g,0,sizeof(g));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(i*j>=w){
g[i][j]=triangle[i*j][w];
for(int l=1;l<=i;l++)
for(int r=1;r<=j;r++)
if(l<i||r<j)
g[i][j]=(g[i][j]-g[l][r]*triangle[i][l]%MOD*triangle[j][r]%MOD+MOD)%MOD;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int l=0;l<=i;l++)
for(int r=0;r<=j;r++){
int u=i-l,v=j-r;
if(u*v>=w)
dp[i][j][k]=(dp[i][j][k]+dp[l][r][k-1]*g[u][v]%MOD*triangle[n-l][u]%MOD*triangle[m-r][v]%MOD)%MOD;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=(ans+dp[i][j][c])%MOD;
printf("%lld\n",ans);
}
void init(){
n=read();m=read();c=read();
S=n*m;
for(int i=0;i<=S;i++)triangle[i][0]=1;
for(int i=1;i<=S;i++)
for(int j=1;j<=i;j++)
triangle[i][j]=(triangle[i-1][j-1]+triangle[i-1][j])%MOD;
dp[0][0][0]=1;
}
int main(){
init();
work();
return 0;
}