WUST OJ 1287:B304(DP)

1287: B304

Time Limit: 1 Sec   Memory Limit: 128 MB   64bit IO Format: %lld
Submitted: 9   Accepted: 4
[ Submit][ Status][ Web Board]

Description

B304 has a special meaning to every member of WHUACM training team. In fact, it is the training room of WHUACM. Year by year, the members of the team trained there. The current team leader Xioumu is not only an ACMer but also an artist. He plans to purchase some flowers to make the training room more beautiful. There are N rows of desks in B304 and each row contains M columns. He wants to put the flowers on some of them. For each desk, there shouldn‟t be more than one flower putting on it. Xioumu doesn‟t care the total amount of the flower, even if the amount is zero. Only he cares is after he finish his work, for each row and each column, there should be odd number of flowers in total. Now he needs your help. He has already known N and M and he wants to know how many ways there are which satisfied above restriction.

Input

There are multiple test cases. Each case contains two integer numbers N and M. Technical Specification 1 <= N, M <= 100

Output

For each case, output the result in one line. Since the result may be very large, just output the result mod 1,000,000,007.

Sample Input 

2 2

Sample Output

2

HINT

Source

思路:看到题目应该是DP计数,但是不能一格一格来DP,只能一行一行来DP。d[i][j]表示到[1,i]行每行花朵数量均为奇数时,其中有j列的花朵数量为奇数。那么答案就是d[n][m]。状态转移方程看代码。

#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
typedef long long ll;
ll d[101][101];
ll c[101][101];
int main()
{
    memset(c,0,sizeof c);
    c[0][0]=1;
    for(int i=1;i<=100;i++)
    {
        c[i][0]=1;
        for(int j=1;j<=i;j++)c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD;
    }
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(d,0,sizeof d);
        for(int i=1;i<=m;i+=2)d[1][i]=c[m][i];
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<=m;j++)//表示当前有j列的花朵的数量为奇数
            {
                if(d[i][j]==0)continue;//此处的优化让代码勉强能过,但看别人AC花的时间貌似还能优化。
                for(int k=1;k<=m;k+=2)//下一行放k朵花,k为奇数
                {
                    for(int p=0;p<=k&&p<=j;p++)//下一行放p朵花在奇数列(即把p列花朵数量为奇数的变成偶数的),k-p朵花放在偶数列
                    {
                        if(j+k-p>m)continue;
                        d[i+1][j-p+k-p]+=d[i][j]*(c[m-j][k-p]*c[j][p]%MOD)%MOD;
                        d[i+1][j-p+k-p]%=MOD;
                    }
                }
            }
        }
        printf("%lld\n",d[n][m]);
    }
    return 0;
}



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值