越狱(快速幂取模)

来源:互联网 发布:js 弹出div层 居中 编辑:程序博客网 时间:2024/06/06 15:13

问题描述:

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

输入:

输入两个整数M,N.1<=M<=10^8,1<=N<=10^12

输出:

可能越狱的状态数,模100003取余

例子输入:

2 3

例子输出:

6

6种状态为(000)(001)(011)(100)(110)(111)


思路:

所有的可能的情况数为:m^n,不发生越狱的情况数为:m*(m-1)^(n-1),所以发生越狱的情况数为:m^n-m*(m-1)^(n-1),所以答案为:(m^n-m*(m-1)^(n-1))%mod。注意:1. 取模;2.快速幂

1.取模运算

1)(m^n-m*(m-1)^(n-1))%mod

 = (m*(m^(n-1)-(m-1)^(n-1)))%mod

 = ((m%mod)*((m^(n-1)-(m-1)^(n-1))%mod)))%mod  (3)

 =((m%mod)*((m^(n-1)%mod)-((m-1)^(n-1)%mod)+mod)%mod))%mod (2)

令:m^(n-1)%mod=quick_power(m,n-1)   (m-1)^(n-1)%mod=quick_power(m-1,n-1)

 =((m%mod)*((a-b+mod)%mod))%mod

 =m*((a-b+mod)%mod)%mod%mod  (6)

 =m*((a-b+mod)%mod)%mod


2)运算规则

模运算与基本四则运算有些相似,但是除法例外。其规则如下:
  1. (a + b) % p = (a % p + b % p) % p (1)
  2. (a - b) % p = (a % p - b % p) % p (2)
  3. (a * b) % p = (a % p * b % p) % p (3)
  4. a ^ b % p = ((a % p)^b) % p (4)
       结合律:
  • ((a+b) % p + c) % p = (a + (b+c) % p) % p (5)
  • ((a*b) % p * c)% p = (a * (b*c) % p) % p (6)
交换律:
  • (a + b) % p = (b+a) % p (7)
  • (a * b) % p = (b * a) % p (8)

   分配律:
       (a+b) % p = ( a % p + b % p ) % p (9)
       ((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p (10)

2.快速幂取模

先讨论无需取模的

  当b为偶数时:ab=a(b/2)*2=(a2)b/2

  当b为奇数时:ab=a*ab-1=a*(a2)(b-1)/2

例如:210=(22)5=(22)*[(22)2]2

             211=2*(22)5=2*(22)*[(22)2]2

归纳总结得到:

     当指数大于1时,若为偶数,则将指数除以2,底数平方

                                   若为奇数,则先提出一个为底数的系数(可直接把该系数乘进ans中),所以指数减1,然后再按照偶数的办法做

       不断迭代下去,当指数为1时,则直接得出答案


  最后只要将每次相乘时取模即可,时间复杂度O(log2b)

快速幂取模代码:

inline int mi(int a,int b) {     int ans=1;     while (b)     {         if (b&1) ans=ans*a%mo;         b>>=1;         a=a*a%mo;     }     return ans; }

综上,该题的代码如下:

#include <bits/stdc++.h>using namespace std;typedef long long ll;const ll  mod=100003;ll n,m;ll quick_power(ll x,ll y){     ll ans=1;     while(y){         if(y&1) ans=(ans*x)%mod;            x=(x*x)%mod;            y>>=1;     }     return ans; } int main(){     scanf("%lld%lld",&m,&n);     printf("%lld\n",m*((quick_power(m,n-1)-quick_power(m-1,n-1)+mod)%mod)%mod);     return 0; }