洛谷P3197-越狱

一道容斥原理和组合数学的应用题,如果只是一味的去想办法枚举目标状态,那么题目也不会眷顾你.

题目大意:

监狱有 \(n\) 个牢房,每个房间关押一个犯人,有 \(m\) 种宗教(抱歉我是无神论者)。
每个犯人会信仰其中一种宗教(非得信神是把).如果相邻房间的犯人信仰的宗教相同,
就会发生越狱(被神父洗脑了).求有多少种情况会发生越狱,并将方案数对 \(100003\) 取模。

对于 \(100\%\) 的数据,保证 \(1\le m \le 10^8 , 1\le n \le 10^{12}\) .

解题思路:

虽然不知道哪来这么多宗教(信仰外星人),但是数据已经告诉你了要用特殊的方法计算。

如果我们直接去计算可以越狱的方案数,很显然,这很难实现。那么,如果往相反的方向去想呢?

对于总方案数,每个人都可以选 \(m\) 种宗教,所以总共有 \(m^n\) 种方案。

现在考虑不与相邻相同宗教的方案数,由于不能与旁边相同,所以除了第一个牢房能选 \(m\) 个宗教,
后面的牢房都只能选 \(m-1\) 种宗教,以此类推,总方案数为 \(m * \left ( m-1\right )^{n-1}\)

由总方案数减去不相同的方案数,留下来的就是相邻,也就是题目所需要求的方案。结果为:

\[m^n - m * \left ( m-1\right )^{n-1} \]

因为基数较大,可以用快速幂求,并在中间边求边取余。

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 100003;
int n, m;
int q_pow(int a, int b) {
	int ans = 1;
	while (b) {
		if (b & 1) ans = (ans * a) % mod;
		a = (a * a) % mod;
		b >>= 1;
	}
	return ans;
}
signed main() {
	cin >> m >> n;
	int p = q_pow(m, n);
	int q = (m * q_pow(m - 1, n - 1)) % mod;
	cout << (p - q + mod) % mod;
}

感谢观看!

posted @ 2025-06-22 12:59  Cai_hy  阅读(17)  评论(0)    收藏  举报