监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
标签:
监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
输入两个整数M,N.1<=M<=10^8,1<=N<=10^12
可能越狱的状态数,模100003取余
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 #include<bits/stdc++.h> 2 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<<ans; 26 return 0; 27 }
标签:
原文地址:http://www.cnblogs.com/CXCXCXC/p/4661980.html