1. 程式人生 > >LightOJ - 1246 Colorful Board(DP+組合數)

LightOJ - 1246 Colorful Board(DP+組合數)

show 得到 需要 lld http ans while fine template

http://lightoj.com/volume_showproblem.php?problem=1246

題意

有個(M+1)*(N+1)的棋盤,用k種顏色給它塗色,要求曼哈頓距離為奇數的格子之間不能塗相同的顏色,每個格子都必須有顏色,問可行的方案數。

分析

經一波分析,根據曼哈頓距離為奇數這一信息,可以將棋盤分為兩部分,也就是相鄰格子不能有相同顏色。一種顏色只能在一個部分中出現。現在考慮對一個部分的格子操作,

dp[i][j]表示i個格子選擇用了j種顏色的方案數,於是可以得到這樣的遞推式:dp[i][j]=dp[i-1][j-1]*j+dp[i-1][j]*j。得到dp數組後還不夠,需要枚舉兩個部分使用的顏色數,兩層循環,其中選擇顏色的方案數則用組合數來算。

#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#include<set>
#define rep(i,e) for(int i=0;i<(e);i++)
#define rep1(i,e) for(int i=1;i<=(e);i++)
#define
repx(i,x,e) for(int i=(x);i<=(e);i++) #define X first #define Y second #define PB push_back #define MP make_pair #define mset(var,val) memset(var,val,sizeof(var)) #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define
pd(a) printf("%d\n",a) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define sclll(a,b,c) scanf("%lld%lld%lld",&a,&b,&c) #define IOS ios::sync_with_stdio(false);cin.tie(0) using namespace std; typedef long long ll; template <class T> void test(T a){cout<<a<<endl;} template <class T,class T2> void test(T a,T2 b){cout<<a<<" "<<b<<endl;} template <class T,class T2,class T3> void test(T a,T2 b,T3 c){cout<<a<<" "<<b<<" "<<c<<endl;} const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3fll; const ll mod = 1e9+7; int T; void testcase(){ printf("Case %d: ",++T); } const int MAXN = 3e5+10; const int MAXM = 30; ll dp[250][55],C[55][55]; void init(){ mset(C,0); for(int i=0;i<55;i++){ C[i][0]=1; for(int j=1;j<=i;j++){ C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; } } for(int i=1;i<250;i++){ dp[i][1]=1; for(int j=2;j<55;j++){ dp[i][j]=(dp[i-1][j]*j+dp[i-1][j-1]*j)%mod; } } } int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif // LOCAL init(); int t; scd(t); T=0; while(t--){ int m,n,k; scddd(m,n,k); m++,n++; ll ans=0; if(m==n&&m==1) ans=k; else{ int n1=(n+1)/2*((m+1)/2)+n/2*(m/2); int n2=m*n-n1; for(int i=1;i<k;i++){ for(int j=1;i+j<=k;j++){ ans=(ans+(C[k][i]*C[k-i][j])%mod*((dp[n1][i]*dp[n2][j])%mod))%mod; } } } testcase(); cout<<ans<<endl; } return 0; }

LightOJ - 1246 Colorful Board(DP+組合數)