1008: [HNOI2008]越狱
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5247 Solved: 2270[][][]Description
监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
Input
输入两个整数M,N.1<=M<=10^8,1<=N<=10^12
Output
可能越狱的状态数,模100003取余
Sample Input
Sample Output
HINT
6种状态为(000)(001)(011)(100)(110)(111)
此题属于一道组合数学问题,我一开始还以为是DP。。。。
所有的可能宗教信仰方案为:M^N,因为有N个监狱,每个监狱的犯人的宗教有M中选择
不能越狱(相邻两个房间的人的宗教信仰不同)的方案为:M*(M-1)^(N-1),第一个监狱里的犯人可以有M个宗教选择,第二个监狱里的犯人可以有M-1中选择(保证和第一个监狱里的犯人不重复即可),同理,第三个监狱的犯人只需和第二个监狱里的不一样,也是M-1个选择,,,,以此类推,共N个监狱,除第一个监狱有M个选择,其余N-1个监狱只有M-1中选择,所以M*(M-1)^(N-1)
于是最终的答案: [M^N-M*(M-1)^(N-1)]%100003
由于N,M都比较大,所以借助了快速幂(讲解:www.cnblogs.com/CXCXCXC/p/4641812.html)
中间有很多细节需要mod,处处mod,mod前想想对不对,还有((M^N)%mod-(M*(M-1)^(N-1))%mod)%mod有可能为负数,可以特判,若ans<0,ans+=mod 也可以((M^N)%mod+mod-(M*(M-1)^(N-1))%mod)%mod 即中间加个mod
1 #include2 using namespace std; 3 typedef long long LL; 4 const int mod=100003; 5 LL M,N; 6 LL ans; 7 8 LL poww(LL a,LL b){ 9 LL base=a;10 LL ans1=1;11 while(b!=0){12 if(b&1!=0){13 ans1=ans1*base;14 ans1=ans1%mod;15 }16 base=base*base;17 base=base%mod;18 b=b>>1;19 }20 return ans1%mod;21 }22 int main(){23 cin>>M>>N;24 ans=(poww(M,N)+mod-(M*poww(M-1,N-1))%mod)%mod;25 cout<