1 1 2 2 2 3
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; }
HDU 5155 Harry And Magic Box(组合数学+容斥)
原文:http://blog.csdn.net/u013582254/article/details/42403205