信息学奥赛一本通 1618:越狱 | 洛谷 P3197 [HNOI2008] 越狱

【题目链接】

ybt 1618:越狱
洛谷 P3197 [HNOI2008] 越狱

【题目考点】

1. 补集转化

当集合本身元素个数很难分析,但全集和补集都很容易求解时,可以先求出全集和补集的元素个数,二者相减就是所求集合元素的个数。

例:求从5个小球的排列中选出2个不相邻的小球的情况数。

5个小球中选出2个小球的总方案数是 C 5 2 C_5^2 C52,选出2个相邻小球的情况有4种,那么选出两个不相邻小球的方案数为总方案数减去5个小球中选出2个相邻小球的方案数,即 C 5 2 − 4 = 6 C_5^2-4=6 C52−4=6

2. 快速幂
3. 费马小定理

【解题思路】

该问题可以等价为: n n n个数值范围为 [ 1 , m ] [1,m] [1,m]的整数构成序列,求存在相邻两元素数值相等的序列的数量。

这样满足要求的序列很难求。可以考虑求其"补集"的情况数量,也就是该问题"反面"的情况。

先求出"全集"的情况数,即 n n n个数值范围为 [ 1 , m ] [1,m] [1,m]的整数构成的序列的总数量。

第1步确定第1个元素的值,可以是 [ 1 , m ] [1,m] [1,m]中的整数,共 m m m种情况。

第2步确定第2个元素的值,可以是 [ 1 , m ] [1,m] [1,m]中的整数,共 m m m种情况。

...

第 n n n步确定第 n n n个元素的值,可以是 [ 1 , m ] [1,m] [1,m]中的整数,共 m m m种情况。

根据乘法原理, n n n个数值范围为 [ 1 , m ] [1,m] [1,m]的整数构成的序列的总数量为 m n m^n mn。

接下来求"补集"的情况数。考虑不满足"存在相邻两元素数值相等"的序列,即相邻元素数值都不相等的序列。

第1步确定第1个元素的值,可以是 [ 1 , m ] [1,m] [1,m]中的整数,共 m m m种情况,假设选定的数值为 a 1 a_1 a1

第2步确定第2个元素的值,可以是 [ 1 , m ] [1,m] [1,m]中的不等于 a 1 a_1 a1的整数,共 m − 1 m-1 m−1种情况,假设选定的数值为 a 2 a_2 a2

第3步确定第3个元素的值,可以是 [ 1 , m ] [1,m] [1,m]中的不等于 a 2 a_2 a2的整数,共 m − 1 m-1 m−1种情况,假设选定的数值为 a 3 a_3 a3

...

第 n n n步确定第 n n n个元素的值,可以是 [ 1 , m ] [1,m] [1,m]中的不等于 a n − 1 a_{n-1} an−1的整数,共 m − 1 m-1 m−1种情况,假设选定的数值为 a n a_n an

因此相邻元素数值都不想等的序列数量为 m ⋅ ( m − 1 ) n − 1 m\cdot(m-1)^{n-1} m⋅(m−1)n−1

n n n个数值范围为 [ 1 , m ] [1,m] [1,m]的整数构成序列中,存在相邻两元素数值相等的序列的数量,为总序列数量减去相邻元素数值都不想等的序列的数量,即 m n − m ⋅ ( m − 1 ) n − 1 m^n-m\cdot(m-1)^{n-1} mn−m⋅(m−1)n−1。

设 P = 100003 P=100003 P=100003,可以通过质数判定方法确定 P P P为质数。

因此所求结果为:
( m n − m ⋅ ( m − 1 ) n − 1 )   m o d   P = ( m n   m o d   P − ( m ⋅ ( m − 1 ) n − 1 )   m o d   P )   m o d   P (m^n-m\cdot(m-1)^{n-1}) \bmod P\\ =(m^n \bmod P-(m\cdot(m-1)^{n-1})\bmod P)\bmod P (mn−m⋅(m−1)n−1)modP=(mnmodP−(m⋅(m−1)n−1)modP)modP

可以直接使用快速幂求解。

也可以使用费马小定理降幂求解。根据费马小定理,当 p p p为质数时: a b   m o d   p = ( a   m o d   p ) b   m o d   ( p − 1 )   m o d   p a^b\bmod p = (a\bmod p)^{b\bmod (p-1)}\bmod p abmodp=(amodp)bmod(p−1)modp

所以: ( m n   m o d   P − ( m ⋅ ( m − 1 ) n − 1 )   m o d   P )   m o d   P = ( ( m   m o d   P ) n   m o d   ( P − 1 ) − ( m   m o d   P ) ( ( m − 1 )   m o d   P ) ( n − 1 )   m o d   ( P − 1 ) )   m o d   P (m^n \bmod P-(m\cdot(m-1)^{n-1})\bmod P)\bmod P\\ =((m\bmod P)^{n\bmod (P-1)}-(m\bmod P)((m-1)\bmod P)^{(n-1)\bmod (P-1)})\bmod P (mnmodP−(m⋅(m−1)n−1)modP)modP=((mmodP)nmod(P−1)−(mmodP)((m−1)modP)(n−1)mod(P−1))modP

注意:两项相减结果可能为负,所以最后一步必须进行数学取模。

【题解代码】

解法1:直接使用快速幂求解
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define MOD(a, b) (((a)%(b)+(b))%(b))
const int P = 100003;
typedef long long LL;
LL fastPow(LL a, LL b, LL m)
{
	LL r = 1;
	while(b > 0)
	{
		if(b%2 == 1)
			r = r*a%m;
		a = a*a%m;
		b /= 2;
	}
	return r;
}
int main()
{
	LL m, n;
	cin >> m >> n;
	cout << MOD(fastPow(m, n, P)-m*fastPow(m-1, n-1, P), P);
	return 0;
}
解法2:使用费马小定理降幂求解
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define MOD(a, b) (((a)%(b)+(b))%(b))
const int P = 100003;
typedef long long LL;
LL fastPow(LL a, LL b, LL m)
{
	LL r = 1;
	while(b > 0)
	{
		if(b%2 == 1)
			r = r*a%m;
		a = a*a%m;
		b /= 2;
	}
	return r;
}
int main()
{
	LL m, n;
	cin >> m >> n;
	cout << MOD(fastPow(m%P, n%(P-1), P)-m*fastPow((m-1)%P, (n-1)%(P-1), P), P);
	return 0;
}
相关推荐
君义_noip15 小时前
信息学奥赛一本通 1453:移动玩具 | 洛谷 P4289 [HAOI2008] 移动玩具
c++·算法·信息学奥赛·csp-s
玉树临风ives5 天前
atcoder ABC436 题解
c++·算法·leetcode·atcoder·信息学奥赛
君义_noip7 天前
洛谷 P4777 【模板】扩展中国剩余定理(EXCRT)
算法·数论·信息学奥赛·csp-s
君义_noip7 天前
信息学奥赛一本通 1640:C Looooops
c语言·数论·信息学奥赛·csp-s
君义_noip11 天前
信息学奥赛一本通 4017:【GESP2309三级】小杨的储蓄 | 洛谷 B3867 [GESP202309 三级] 小杨的储蓄
c++·算法·gesp·信息学奥赛
ComputerInBook20 天前
理解数学概念——素数(质数)(prime)
算法·数论·质数·素数
No0d1es1 个月前
2025年 CSP-J1 入门级初赛 C++真题
开发语言·c++·青少年编程·csp·信息学奥赛·初赛
让我们一起加油好吗2 个月前
【数论】裴蜀定理与扩展欧几里得算法 (exgcd)
算法·数论·裴蜀定理·扩展欧几里得算法·逆元
让我们一起加油好吗2 个月前
【数论】乘法逆元(求逆元的三种方式)
算法·数论·费马小定理·扩展欧几里得算法·乘法逆元