LightOJ - 1246 Colorful Board(DP+组合数)

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

原文地址:https://www.cnblogs.com/fht-litost/p/9313240.html

时间: 2024-10-06 00:54:00

LightOJ - 1246 Colorful Board(DP+组合数)的相关文章

LightOJ - 1246 - Colorful Board(DP)

链接: https://vjudge.net/problem/LightOJ-1246 题意: You are given a rectangular board. You are asked to draw M horizontal lines and N vertical lines in that board, so that the whole board will be divided into (M+1) x (N+1) cells. So, there will be M+1 ro

1246 - Colorful Board

   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB You are given a rectangular board. You are asked to draw M horizontal lines and N vertical lines in that board, so that the whole board will be divided into (M+1) x (N+1) c

HDU 4248 A Famous Stone Collector(DP + 组合数)

题目链接:点击打开链接 思路:DP + 组合数. 用d[i][j]表示前第i种颜色的石头, 已经用了j个的方法数, 每次枚举第i种石头放多少个, 假设放k个, 那么相当于从j个位置中选k个, 预处理组合数就行了. 细节参见代码: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector&

hdu 4945 2048 (dp+组合数)

2048 Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 840    Accepted Submission(s): 199 Problem Description Teacher Mai is addicted to game 2048. But finally he finds it's too hard to get 2048.

noj 2033 一页书的书 [ dp + 组合数 ]

传送门 一页书的书 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 53            测试通过 : 10  题目描述 一页书前辈作为一位得道高僧,在他无悔的生涯中创作了许多经典,被世人称作百世经纶.这一天有m个粉丝来膜拜书大,书大很开心,决定送他们每人一本经典.已知一页书一共创作了n部作品,每部作品分别有a1.a2…an份藏本,那么书大一共可以有多少种送书的选择呢?(由于计算结果可能很大,请把结果对

2014多校8(1001)hdu4945(dp+组合数计数+求逆元)

2048 Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 566    Accepted Submission(s): 129 Problem Description Teacher Mai is addicted to game 2048. But finally he finds it's too hard to get 2048.

ZOJ 3791 An easy game DP+组合数

给定两个01序列,每次操作可以任意改变其中的m个数字 0变 1  1 变 0,正好要变化k次,问有多少种变法 dp模型为dp[i][j],表示进行到第i次变化,A,B序列有j个不同的 变法总和. 循环k次,每次针对m,向那j个不同 分1-j个即可,不过要用到组合数,因为对每个数操作不同都不一样 最后结果就是 dp[k][0] #include <iostream> #include <cstdio> #include <cstring> #include <alg

lightoj 1095 - Arrange the Numbers(dp+组合数)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1095 题解:其实是一道简单的组合数只要推导一下错排就行了.在这里就推导一下错排 dp[i]=(i-1)*dp[i-2](表示新加的那个数放到i-1中的某一个位置然后那个被放位置的数放在i这个位置就是i-2的错排)+(i-1)*dp[i-1](表示新加的那个数放到i-1中的某一个位置然后用那个位置被占的数代替i这个位置的数就是i-1的错排) #include <iostream

Lightoj 1044 - Palindrome Partitioning (DP)

题目链接: Lightoj  1044 - Palindrome Partitioning 题目描述: 给一个字符串,问至少分割多少次?分割出来的子串都是回文串. 解题思路: 先把给定串的所有子串是不是回文串处理出来,然后用dp[i] 表示 从起点到串i的位置的最少分割次数,然后结合处理出来的回文串转移一下即可! 还是好蠢哦!自己竟然感觉是一个区间DP,但是n又那么大,完全不是区间DP的作风啊! 1 #include <cmath> 2 #include <cstdio> 3 #i