HDU5155 Harry And Magic Box

Harry And Magic Box

傳送門1
傳送門2
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.0n,m50.

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
11

11
10

11
01

10
11

01
11

01
10

10
01

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


題意

在n*m的矩陣內每一行每一列都有鑽石,問鑽石分佈的種類。

分析

法一

定義dp[i][j] 表示前i行,都滿足了每一行至少有一個寶石的條件,且只有j列滿足了有寶石的條件的情況有多少種。
枚舉第i+1行放的寶石數k,這k個當中有t個是放在沒有寶石的列上的,那麼我們可以得到轉移方程:
dp[i+1][j+t]+=dp[i][j]CtmjCktj

法二

定義f(i) 爲每一行有i 列必不存在鑽石,則有Cim 種。
而對於其他mi 列可放可不放,但不能全都不放,且有n 行。於是有

f(i)=Cim(2mi1)n
种放法。
再根據容斥原理:得出結果ans=f(0)f(1)+f(2)......f(n)

CODE

法一
#include<cstdio>
#include<memory.h>
#define mod 1000000007
#define N 55
#define FOR(i,a,b) for(int i=(a),i##_END_=(b);i<=i##_END_;i++)
typedef long long LL;
int n,m;
LL C[N][N],dp[N][N];

int main() {
    C[0][0]=1;
    FOR(i,1,50){
        C[i][i]=C[i][0]=1;
        FOR(j,1,i-1)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
    while(~scanf("%d%d",&n,&m)) {
        memset(dp,0,sizeof dp);
        FOR(i,1,m)dp[1][i]=C[m][i];
        FOR(i,2,n)FOR(k,1,m)FOR(z,0,k)FOR(j,k-z,m-z)
            dp[i][j+z]=(dp[i][j+z]+dp[i-1][j]*C[j][k-z]%mod*C[m-j][z])%mod;
        printf("%lld\n",dp[n][m]);
    }
    return 0;
}
法二
#include<cstdio>
#include<memory.h>
#define mod 1000000007
#define N 55
#define FOR(i,a,b) for(int i=(a),i##_END_=(b);i<=i##_END_;i++)
typedef long long LL;
int n,m;
LL C[N][N],pow[N];

int main() {
    pow[0]=C[0][0]=1;
    FOR(i,1,50) {
        C[i][i]=C[i][0]=1;
        pow[i]=(pow[i-1]<<1)%mod;
        FOR(j,1,i-1)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
    while(~scanf("%d %d",&n,&m)) {
        if(n<=1||m<=1) {
            puts("1");
            continue;
        }
        int f=1;
        int ans=0,s;
        FOR(i,0,m) {
            s=C[m][i];
            FOR(j,1,n)s=1LL*s*(pow[m-i]-1)%mod;
            ans=(ans+f*s)%mod;
            f=-f;
        }
        if(ans<0)ans+=mod;
        printf("%d\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章