越狱(快速幂取模)

问题描述:

监狱有连续编号为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;
 }










  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值