HDU-5155-Harry And Magic Box(容斥)

HDU-5155-Harry And Magic Box(容斥)

传送门

这道题是容斥+快速幂
这道题跟我前几天做的CF上面一道题差不多。CFRound 86E题

题目大意:n * m的网格点上面有宝石jewel,其中这些网格点上面,哈里从左侧面看,可以看到每一行都闪闪发光,说明这个网格上每行都至少有一个宝石;哈里从前面看网格,可以看到每一列上都闪闪发光,说明这个网格点上每列都至少有一个宝石。
问有多少种不同的方案满足题目每行和每列都至少有一个宝石的情况。
答案mod 1e9 + 7;(自从上次遇到过一个1e8 + 7的时候,我再也不敢自作主张统一认为都是1e9 + 7了。)

本题思路:这道题我们用容斥来解决。
我们规定:f(x)代表至少有x列一个钻石也没有的情况。
那么我们先选定x列没有宝石,方案数是(x, m);从总的m列中选取x列一个宝石都不放。
那么对于其余的列数即m - x列:随意放不放宝石,放与不放两种选择,那么就是2^(m - x)次方的情况。我们需要减掉全都没有放宝石的情况。于是就-1。
在这些情况下,每一种情况对应着n行的选择,即(2^(m-x) - 1)^n;
然后用容斥:
f(0) - f(1) + f(2) - f(3)…一直到m
简单解释一下:f(0)至少有0列一个钻石也没有是总的情况。
然后f(1)代表至少有1列一个钻石也没有
f(2)代表至少有2列一个钻石也没有
因为减去了f(1),后来加上f(2);
假设是第a列和第b列一个钻石也没有,那么我们在d(1)中已经减去了这种情况,之后我们通过f(2)加回来。
减去f(3);f(3)代表至少有3列一个钻石也没有,假设这三列是x, y, z;
那么x, y; x, z; y, z这三种情况是两列都没有钻石的,我们在f(2)加了一次,需要在f(3)情况中减掉。
…这样下去,也就对应着计数是减,偶数是加。

总体思路说完啦~
然后就是组合部分,题目数据范围在50以内,所以我们可以预处理出组合数,不进行预处理其实也行。反正不是很大。然后计算幂的时候用快速幂计算即可。
记得取模哦~

代码部分:

#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
const int N = 55;
typedef long long ll;

ll c[N][N];
int n, m;

void init()
{
	c[0][0] = 1;
	for (int i = 1; i <= 50; i++)
	{
		c[i][0] = c[i][i] = 1;
	}
	for (int i = 2; i <= 50; i++)
	{
		for (int j = 1; j < i; j++)
		{
			c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
		}
	}
}

ll npower(ll a, int n)
{
	ll res = 1;
	while (n)
	{
		if (n & 1)
		{
			res = res * a % mod;
		}
		a = a * a % mod;
		n >>= 1;
	}
	return res;
}

int main()
{
	init();
	while (~scanf ("%d%d", &n, &m))
	{
		ll ans = 0;
		for (int i = 0; i <= m; i++)
		{
			ll t = c[m][i] * npower(npower(2, m - i) - 1, n) % mod;
			if (i & 1)
			{
				ans = (ans + mod - t) % mod;
			}
			else
			{
				ans = (ans + t) % mod;
			}
		}
		cout << ans % mod << endl;
	}
	return 0;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

娃娃酱斯密酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值