#10196. 「一本通 6.1 练习 3」越狱(快速幂系列)

题目描述题目链接在此

原题来自:HNOI 2008

监狱有连续编号为 111 到 nnn 的 nnn 个房间,每个房间关押一个犯人。有 mmm 种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人信仰的宗教相同,就可能发生越狱。求有多少种状态可能发生越狱。

【输入格式】

输入两个整数 mmm 和 nnn。

【输出格式】

可能越狱的状态数,对 100003100003100003 取余。

【样例输入】

2 3

【样例输出】

6

【样例说明】

所有可能的 666 种状态为:{0,0,0},{0,0,1},{0,1,1},{1,0,0},{1,1,0},{1,1,1}\{0,0,0\},\{0,0,1\},\{0,1,1\},\{1,0,0\},\{1,1,0\},\{1,1,1\}{0,0,0},{0,0,1},{0,1,1},{1,0,0},{1,1,0},{1,1,1}。

【数据范围与提示】

对于全部数据,1≤m≤108,1≤n≤10121\le m\le 10^8,1\le n\le 10^{12}1≤m≤10​8​​,1≤n≤10​12​​。

思路:这道题的确也是快速幂,但是比转圈游戏更不好找到,因为他没有详细出现平方这样的字眼,但是仔细想想,还是能想出点头绪的,因为我们可以从越狱和不越狱的可能性出发,进行深度思考,其实我们只要能够理解到 m^n就是全部的可能性,只要能推出这个就一定能推出这是快速幂,而且也会离答案的公式越来越近,公式推导在代码里面。

代码实现

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define z 100003
typedef long long ll;
ll n,m;
ll power(ll x,ll y)
{
    ll ans=1%z; x=x%z;
    while(y>0)
    {
        if(y&1) ans=ans*x%z;
        y=y>>1; x=x*x%z;  
    }
    return ans;
}
int main()
{
	scanf("%lld%lld",&m,&n);
	ll a=power(m,n);
	/*表示所有的可能方案,包括越狱和不越狱 
	比如说m为2,n为3,那么可能性为m^n=8,就是 0 0 0,0 0 1, 0 1 0, 0 1 1
	1 0 0,1 0 1, 1 1 0, 1 1 1  
	ll b=m*power(m-1,n-1);
	/*
	不越狱的可能方案:
	比如说:有三种宗教,那么不能越狱的就是 1 0 1 , 0 1 0 两种可能,就是m-1
	那么如果有三个房间,第一个房间的宗教选择是1,
	那么后面两个房间就是 1 0 , 0 1两种可能,就是n-1 
	*/ 
	ll answer=((a-b)%z+z)%z;
	/*
	这个就是可以越狱的可能方案,mod是题目要求,+z是因为防止 -mod ,最后再mod就好了 
	*/ 
    printf("%lld\n",answer);
	return 0;
}

这道题只要理清楚总的可能性,不能越狱的可能性,可以越狱的可能性,就可以推出最终的公式,最后的答案可以连在一起输出,但是我为了理解和调试所以就分开输出了a和b,这个不太影响,洛谷上面也有这道题,挺好理解的,也蛮经典的。难度系数大概也是3.5吧,因为要理解这是快速幂和推公式,如果一开始就不能理解这是快速幂,那么这道题就做不出来。

猜你喜欢

转载自blog.csdn.net/qq_42367531/article/details/82047947