HDU 5155 Harry And Magic Box(组合数学+容斥)

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

容斥+组合知识:感谢凡神写的题解点击打开链接

我们首先要保证的是每行都有1,这是前提。然后要想得到答案我们可以枚举i

列全为0(共有C(m,i)选法),然后就是考虑每行还剩的(m-i)个位置,我们

此时可以随意放置01(2^(m-i)方法),但是为了保证每行都有1故要减1,此时

为(2^(m-i)-1).然后有n行,所以sum[i]=(2^(m-i)-1)^n,然后我们要从

里面剔除一些东西,就是仅仅第i列全为0(注意刚刚i列全为不是仅仅)

所以要容斥。ans=sum[0]-sum[1]+sum[2]..
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<bitset>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
typedef long long LL;
typedef pair<int,int>pil;
const int maxn=55;
const int MOD=1000000007;
LL c[maxn][maxn];//2^(m-i)-1;
int n,m;
void init()
{
    REPF(i,1,50)
    {
        c[i][0]=c[i][i]=1;
        REPF(j,1,i-1)
           c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
    }
}
LL pow_mod(LL a,int b)
{
    a%=MOD;
    LL ans=1;
    while(b)
    {
        if(b&1)  ans=ans*a%MOD;
        a=a*a%MOD;
        b>>=1;
    }
    return ans;
}
int main()
{
    init();
    while(~scanf("%d%d",&n,&m))
    {
        LL ans=0;
        REPF(i,0,m)
        {
            if(i&1)
                ans=(ans-(pow_mod((1LL<<(m-i))-1,n)*c[m][i])%MOD+MOD)%MOD;
            else
                ans=(ans+(pow_mod((1LL<<(m-i))-1,n)*c[m][i])%MOD)%MOD;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
时间: 2024-08-03 19:45:01

HDU 5155 Harry And Magic Box(组合数学+容斥)的相关文章

HDU 5155 Harry And Magic Box --DP

题意:nxm的棋盘,要求每行每列至少放一个棋子的方法数. 解法:首先可以明确是DP,这种行和列的DP很多时候都要一行一行的推过去,即至少枚举此行和前一行. dp[i][j]表示前 i 行有 j 列都有了棋子,且每行也有棋子. 这题做法: 从第1行到第n行,枚举这一行有k列已至少有一个,再枚举前一行有j列至少有一个,然后枚举这一行新放多少个棋子t,至少一个(因为每行至少一个) 那么有 dp[i][k] += dp[i-1][j]*C[m-j][k-j]*C[j][t-(k-j)], C表示组合数

HDU 5155 Harry And Magic Box

问题描述 有一天,哈利得到了一个神奇的盒子.这个盒子由n*m个格子组成,有一些格子里会有闪闪发光的宝石.但是盒子的顶部和底部都被神奇的魔法封印着,所以哈利没办法从顶部和底部看到盒子的内部.然而,盒子的四边都是透明的,哈利可以从盒子的四边看到里面的情况.哈利发现,这个神奇的盒子,从左边看过去,每一行都闪烁着光芒,从前面看过去,每一列也都闪烁着光芒.哈利想知道,盒子里的宝石有多少种分布情况.答案有可能很大,所以输出答案对1000000007取模. 输入描述 多组输入数据 每组数据一行,输入两个数n

HDU 4059 The Boss on Mars-矩阵+容斥

错了29遍,终成正果..... 根据题意,很容易的可以想到容斥. 然后的问题就是如何求 sum(n)=1^4+2^4+3^4+....+n^4; 有三种道路: 很显然:1^4+2^4+3^4+....+n^4=(n^5)/5+(n^4)/2+(n^3)/3-n/30: 则1,用java的大数去敲这个的代码. 2,用c++敲,但是用到分数取模,求逆元. 3,用c++敲,但是不用这个公式,用矩阵去构造sum(n). 我用的是第三种.但是第三种有的缺陷,就是时间复杂度有点高. 接下来的问题就是如何优化

HDOJ 5155 Harry And Magic Box DP

dp[i][j] 表示 长宽为i,j的矩形的可能的总数 dp[i][j+1] 可由 dp[i][j] 推过来,枚举dp[i][j]所保留的行数(1...i)即可 Harry And Magic Box Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 441    Accepted Submission(s): 209 Problem D

HDU 5147 Harry And Magic Box dp+组合数

点击打开链接 Harry And Magic Box Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 197    Accepted Submission(s): 97 Problem Description One day, Harry got a magical box. The box is made of n*m grids.

UVA 11806 组合数学+容斥

UVA: https://vjudge.net/problem/UVA-11806 题意:给你一个n×mn×m的矩阵网格和kk个人,问有多少种方法使得每一个格子只放一个人,并且第一行,最后一行,第一列,最后一列都有人.直接枚举似乎有难度,我们考虑容斥.rr行cc列放kk个人的方案数是(r×ck)(r×ck),那么由容斥原理,总方案为 ans=U?A?B?C?D+AB+AC+AD+-+ABCDans=U?A?B?C?D+AB+AC+AD+-+ABCD 其中UU表示没有限制的方案数,A,B,C,DA

【HDOJ】5155 Harry And Magic Box

DP.dp[i][j]可以表示i行j列满足要求的组合个数,考虑dp[i-1][k]满足条件,那么第i行的那k列可以为任意排列(2^k),其余的j-k列必须全为1,因此dp[i][j] += dp[i-1][k]*(2^k)*C(j, k). 1 /* 5155 */ 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 6 #define MAXN 51 7 8 const __int64 MOD

[HDOJ 5155] Harry And Magic Box

题目链接:HDOJ - 5155 题目大意 有一个 n * m 的棋盘,已知每行每列都至少有一个棋子,求可能有多少种不同的棋子分布情况.答案对一个大素数取模. 题目分析 算法1: 使用容斥原理与递推. 首先,一个 n * m 的棋盘不考虑任何限制时,可能的分布情况为 2^(n*m) ,除去没有棋子的情况,为 2^(n*m) - 1 . 然后,因为所有的 n 行,m 列都有棋子,所以枚举 ii (1 <= ii <= i) , jj (1 <= jj <= j) .对于枚举的一组 (

HDU - 6513 Reverse It (SYSU校赛C题)(组合数学+容斥)

题目链接 题意:给定一个n*m的矩阵,可以选择至多两个子矩阵将其反转,求能形成多少种不同的矩阵. 任选一个矩阵有$C_{n+1}^{2}C_{m+1}^{2}$种方法,任选两个不同的矩阵有$C_{C_{n+1}^{2}C_{m+1}^{2}}^{2}$种方法,但其中有重复的,需要去重. 重复的情况一共有以下四种: 第一种,两矩阵拼合成一个矩阵,这样的图形有$C_{n+1}^{2}C_{m+1}^{2}$个,重复度(出现的次数)为(n+m-2) 第二种,形成的两个矩阵在同一行或同一列,有$C_{n