【HDU】5155 Harry And Magic Box 【容斥原理】

来源:互联网 发布:少女大召唤知轩藏书 编辑:程序博客网 时间:2024/05/02 18:50

传送门:【HDU】5155 Harry And Magic Box


题目分析:很容易发现容斥的方法,首先我们不管是否每一列都有星星,但是一定保证每一行至少一个星星,因此我们得到了一个方法,这时有方案数(c[m][1]+c[m][2]+...+c[m][m])^n,但是这里包括了不合法的情况,于是我们用容斥减掉。最后的答案就是:

这个就是用了容斥的方法把恰好为1~m-1个列为空的情况全部去掉了,只留下了所有列都非空的情况(注意一开始我们保证至少一列非空了的,因为要保证每一行都有一个数)。

具体这个容斥的原理我只是会用,想知道为什么可以,可以自己搜索下。

本题时间复杂度为O(50^2)的预处理以及每次O(m)的询问。(当然也可以O(50^3)预处理O(1)作答)。

PS:注意n和m其中一个为0就输出0,因为此时宝石无法放,也就没有放法这一说。


代码如下:


#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;typedef long long LL ;#define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )#define clr( a , x ) memset ( a , x , sizeof a )#define cpy( a , x ) memcpy ( a , x , sizeof a )#define ls ( o << 1 )#define rs ( o << 1 | 1 )#define lson ls , l , m#define rson rs , m + 1 , r#define rt o , l , r#define root 1 , 1 , n#define mid ( ( l + r ) >> 1 )const int MAXN = 55 ;const int mod = 1000000007 ;int c[MAXN][MAXN] ;LL sum[MAXN][MAXN] ;int n , m ;void preprocess () {clr ( c , 0 ) ;clr ( sum , 0 ) ;c[0][0] = 1 ;For ( i , 1 , 50 ) {c[i][0] = 1 ;For ( j , 1 , i ) {c[i][j] = ( c[i - 1][j - 1] + c[i - 1][j] ) % mod ;sum[i][1] = ( sum[i][1] + c[i][j] ) % mod ;}For ( j , 2 , 50 ) sum[i][j] = sum[i][j - 1] * sum[i][1] % mod ;}}void solve () {int ans = 0 ;LL sign = 1 ;rep ( i , 0 , m ) {ans = ( ans + sign * c[m][i] * sum[m - i][n] ) % mod ;sign = -sign ;}printf ( "%d\n" , ( ans % mod + mod ) % mod ) ;}int main () {preprocess () ;while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;return 0 ;}


0 0
原创粉丝点击