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.
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的矩陣內每一行每一列都有鑽石,問鑽石分佈的種類。
分析
法一
定義
枚舉第i+1行放的寶石數k,這k個當中有t個是放在沒有寶石的列上的,那麼我們可以得到轉移方程:
法二
定義
而對於其他
再根據容斥原理:得出結果
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;
}