【题解】越狱
题目
题目来源:CCF HNOI2008;
在线评测地址:LG3197。
题目描述
监狱有 \(n\) 个房间,每个房间关押一个犯人,有 \(m\) 种宗教,每个犯人会信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱。
答案对 \(100,003\) 取模。
输入格式
输入只有一行两个整数,分别代表宗教数 \(m\) 和房间数 \(n\)。
输出格式
输出一行一个整数代表答案。
数据规模与约定
对于 \(100\%\) 的数据,保证 \(1\le m\le 10^8\),\(1\le n\le 10^{12}\)。
分析
题意很明确,这是一道离散组合计数题,我们要对所有情况进行计数,并且用含有 \(m\)、\(n\) 的代数式表示。
这里介绍一种比较容易思考的方法——逆向思维,某些机构将其称为「将错就错」法。
很简单,如果一个问题不好直接计数,那么通过 Ta 的反面来计数。也就是反面情况的补集。
对应到这道题,显然直接求相邻是不太可行的,我们不妨考虑反面,即相邻两两不同。
这就是一个很简单的乘法原理了,对于每一个位置,都有 \(m-1\) 种方案,第一个有 \(m\) 种,则共有 \(m\times (m-1)^{n-1}\) 种。
同时,包括了所有情况的全集 \(|U|=m^n\),所以答案就是 \(m^n-m\times (m-1)^{n-1}\),再用一个快速幂优化即可。
Code
#include <cstdio>
using namespace std;
typedef long long ll;
const int mod = 100003;
ll qp(ll b, ll ind)
{
ll cur = 1, mul = b, ans = 1;
while (cur <= ind)
{
if (cur & ind)
ans = ans * mul % mod;
cur <<= 1;
mul = mul * mul % mod;
}
return ans;
}
int main()
{
ll n, m, tmp, ans;
scanf("%lld%lld", &m, &n);
tmp = qp(m, n);
ans = qp(m - 1, n - 1) * m % mod;
printf("%lld\n", ((tmp - ans) % mod + mod) % mod);
return 0;
}
本文来自博客园,作者 5ab,转载请注明链接哦 qwq
博客迁移啦,来看看新博客吧 -> https://5ab-juruo.oier.space/