天天看點

hdu 5155(遞推)

Harry And Magic Box

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 624    Accepted Submission(s): 293

Problem Description

One

day, Harry got a magical box. The box is made of n*m grids. There are

sparking jewel in some grids. But the top and bottom of the box is

locked by amazing magic, so Harry can’t see the inside from the top or

bottom. However, four sides of the box are transparent, so Harry can see

the inside from the four sides. Seeing from the left of the box, Harry

finds each row is shining(it means each row has at least one jewel). And

seeing from the front of the box, each column is shining(it means each

column has at least one jewel). Harry wants to know how many kinds of

jewel’s distribution are there in the box.And the answer may be too

large, you should output the answer mod 1000000007.

Input

There are several test cases.

For each test case,there are two integers n and m indicating the size of the box. 0≤n,m≤50.

Output

For each test case, just output one line that contains an integer indicating the answer.

Sample Input

1 1

2 2

2 3

Sample Output

1

7

25

Hint

There are 7 possible arrangements for the second test case.

They are:

11

10

Assume that a grids is '1' when it contains a jewel otherwise not.

Source

BestCoder Round #25

題意:一個n*m的矩陣,裡面有一些珠寶,保證從行看過去每一行至少都有一個,從列看過去每列至少會有一個,問總共有多少珠寶擺放的可能方式??

題解:巧妙地遞推.

假設dp[i][j]是前 i 行 前 j 列滿足條件的個數

如果 dp[i][j-1] 已經滿足了前 i 行,j-1 列都滿足條件,那麼第j行可以從 (1,n)個随意擺放

dp[i][j] = dp[i][j-1]*(C(i,1)+C(i,2)...+C(i,i)) = dp[i][j-1]*(2^i-1)

如果 dp[i][j-1] 中有k 行沒有放東西,那麼

dp[i][j] = dp[i-k][j-1]*C(i,k)*(C(i-k,0)+C(i-k,1)+C(i-k,2)...+C(i-k,i-k))=dp[i-k][j-1]*C(i,k)*2^(i-k)

/**
假設dp[i][j]是前 i 行 前 j 列滿足條件的個數
如果 dp[i][j-1] 已經滿足了前 i 行,j-1 列都滿足條件,那麼第j行可以從 (1,n)個随意擺放
dp[i][j] = dp[i][j-1]*(C(i,1)+C(i,2)...+C(i,i)) = dp[i][j-1]*(2^i-1)
如果 dp[i][j-1] 中有k 行沒有放東西,那麼
dp[i][j] = dp[i-k][j-1]*C(i,k)*(C(i-k,0)+C(i-k,1)+C(i-k,2)...+C(i-k,i-k))=dp[i-k][j-1]*C(i,k)*2^(i-k)
*/
#include<stdio.h>
#include<iostream>
#include<string.h>
#include <stdlib.h>
#include<math.h>
#include<algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const LL mod = 1000000007;
LL c[55][55];
LL dp[55][55];
void init(){
    for(int i=1;i<55;i++){
        c[i][0]=c[i][i]=1;
        for(int j=1;j<i;j++){
            c[i][j] = (c[i-1][j-1]+c[i-1][j])%mod;
        }
    }
}
LL pow_mod(LL a,LL n){
    LL ans = 1;
    while(n){
        if(n&1) ans = ans*a%mod;
        a = a*a%mod;
        n>>=1;
    }
    return ans;
}
int main()
{
    init();
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++){
            dp[i][1] = 1;
        }
        for(int i=1;i<=m;i++){
            dp[1][i] = 1;
        }
        for(int i=2;i<=n;i++){
            for(int j=2;j<=m;j++){
                dp[i][j] = dp[i][j-1]*(pow_mod(2,i)-1)%mod;
                for(int k=1;k<i;k++){
                    dp[i][j] = (dp[i][j] + dp[i-k][j-1]*c[i][k]%mod*(pow_mod(2,i-k))%mod)%mod;
                }
            }
        }
        printf("%lld\n",dp[n][m]);
    }
    return 0;
}      
上一篇: hdu 5086(遞推)
下一篇: 遞推與遞歸