BZOJ 1008 越狱
题目如下:
Description
监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
Input
输入两个整数M,N.1<=M<=10^8,1<=N<=10^12
Output
可能越狱的状态数,模100003取余
Sample Input
2 3
Sample Output
6
此题,一看数据,首先想到log级别的算法。然后再看题目,数据结构肯定是没指望了。求的是状态数,所以考虑递推和乘法原理。若尝试递推,会发现递推式和通项公式都很难求出来。所以我们换一个角度。正着求求不出来,不妨试试倒着求。很显然的是------所有的状态数=MN。若采用倒着求的方式,则下一个需要计算的是,不发生越狱的情况数=M*(M-1)N-1。为什么呢?对于每一种宗教(M)则会有M-1种宗教和他相邻且不会发生越狱,那么这m-1种宗教的排列方式又有多少种呢?即(M-1)N-1种,所以共有M*(M-1)N-1种情况不会发生越狱。这下明了了。所以答案就是所有情况数减去不发生越狱的情况数--------MN-M*(M-1)N-1。快速幂即可。
#include<cstdio> #include<iostream> #define mod 100003 #define ll long long int using namespace std; ll m,n; ll quick(ll a,ll n) { ll b=1; while(n>0){ if(n&1){ b=b*a%mod; } a=a*a%mod; n=n>>1; } return b; } int main() { scanf("%lld%lld",&m,&n); m%=mod; ll ans1=quick(m,n)%mod; ll ans2=m*quick(m-1,n-1)%mod; ll ans=ans1+mod-ans2; ans%=mod; printf("%lld",ans); }