您的位置:首页 > 编程语言 > C语言/C++

[快速幂]bzoj1008 越狱

2017-05-23 13:21 246 查看
bzoj1008 越狱

监狱有连续编号为1…N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果

相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱

Input

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

Output

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

Sample Input

2 3

Sample Output

6

emm….如果我们用dfs枚举每种不合法情况的话。数据辣么大。你懂的

改变一下思路?

有n个盘子,有m种水果,怎样放能让相邻盘子相同?

看起来这么像小学的奥数题?

一共有m^n次方种情况嘛。

求不合法情况只要求出合法情况用全部减一下

合法情况?

第一个盘子能放m种水果,

那么第二个盘子为了不与第一个盘子的荔枝重复,第二个盘子只能放m-1种水果。

第三个盘子呢?

为了不与第二个盘子的荔枝重复,第三个盘子也是放m-1种荔枝?

(what?m-1种?还要加上第一个盘子的,第一个盘子又不相邻)

n个盘子

后面n-1个盘子都能放(m-1)种

加上第一个就是m*(m-1)^(n-1)

辣么大?for n-1次也会爆啊

好了重点来了

快速幂

在求 a^n 前

我们可以先求出 a^(n/2)

然后 a^(n/2) * a^(n/2) => a^n

这样一直分割下去,我们能得到一个O(log(n))的算法

例如:

求 2^81

要先求 2^40 2^40 * 2^40 * 2 =>2^81

要求 2^40

2^20 * 2^20=> 2^40

发现指数为奇数时分割要补*2

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
long long ksm(long long x,long long y)//这就是那有趣可爱的快速幂
{
long long a=x,b=y,tot=1;
while (b>0)
{
if (b&1) tot=tot*a%100003;
a=a*a%100003;b>>=1;
}
return tot;
}
int main()
{
long long ans,num,all,m,n;
scanf("%lld%lld",&m,&n);
all=ksm(m,n)%100003;
num=ksm(m-1,n-1)*m%100003;
ans=(all-num+100003)%100003;
printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  快速幂 bzoj c++