acm新手小白必看系列之(7)——快速幂取模精讲及例题
给你一个数a,让你求其b次连乘后的结果
当b很小时,一般的循环算法可以解决这个问题(O(B)),但是当b较大时呢
要知道1e18以上,就会long long int 也可能会溢出
而在数论方面这些数又该如何表示?怎样存储?
所以在此我们定义一个模数mod来代替输出即
a^b=k1*mod+t即t=a^b%mod
对于这样的问题,我们将采用分治的思想来解决这种问题。(啥叫分治呢,这个一时半会说不完,一会简单来说)
a^b=((a^(b/n))^n)*a^(b%n)
当n=2时
a^b=(a^(b/2))*(a^(b/2))*a^(b%2)
(a^b)%mod=(a^(b/2))%mod*(a^(b/2))%mod*a^(b%2)%mod
而后对a^(b/2)进行相同的操作
下面解释一下分治是什么
五大算法之一____分治
分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……此法需要大量的练习才能体会。
typedef long long ll;//typedef 类型 新名字;就可以把long long简化成ll来写了
ll quickmod(ll a,ll b,ll c)
{
if(b==1)
return a;
if(!(b&1))
{
ll t=quickmod(a,b/2,c);
return t*t%c;
}
else
{
ll t=quickmod(a,b/2,c);
return t*t%c*a%c;
}
}
typedef long long ll;//typedef 类型 新名字;
ll quickmod(ll a,ll b,ll c)
{
int ret=1;
while(b)
{
if(b&1)
ret=ret*a%c;
a=a*a%c;
b/=2;
}
return ret;
}
相信大家看了这么多还是不太明白,下面来个咱来个“明白题”(白给)
1.白给的快速幂取模
给定A,B,C,计算A^B%C,这里A^B代表A的B次方
。
Input
输入数据有多组,每组数据一行,有3个正整数分别为A,B和C,1<=A,B,C<=1000000000
Output
输出A^B%C的值
Sample Input
2 3 5
8 2 10
Sample Output
3
4
#include //套模板吧,但是要理解其核心
using namespace std;
long long mode(long long a,long long b,long long mod)
{
long long ans=1;
while(b)
{
if(b%2==1)
{b--;ans=ans*a%mod;}
a=a*a%mod;
b=b/2;
}
return ans;
}
int main()
{
long long a,b,c;
while(cin>>a>>b>>c)
printf("%lld\n",mode(a,b,c));
return 0;
}
2.小蓝数学题
xaiolan很喜欢做各种高深莫测的数学题,一天,她在书上看到了这么一道题。a[1]=6,a[2]=18;a[n]=2*a[n-1]+3*a[n-2](n>=3)
,对于给出的某个数字n,求a[n]。xiaolan一想这道题太简单了,可是看到n的范围是(n<=1e18),对于这么大范围的数,xiaolan不知道该怎么做了,聪明的你,快来帮帮库xiaolanjiejie解决这个问题吧。(由于答案可能很大,请将答案对1e9+7(即1000000007)取模)。
Input
一个整数n(1<=n<=1e18)
Output
a[n]对1e9+7取模后的答案
Sample Input
5
Sample Output
486
关键点推出a[n]=6乘3的(n-1)次幂
#include
using namespace std;
typedef long long ll;
ll n,mod=1e9+7;
ll quickmod(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1)s=s*a%mod;
a=a*a%mod;
b=b/2;
}
return s;
}
int main()
{
ios::sync_with_stdio(false);//取消同步,详请看往期
cin>>n;
printf("%lld\n",6*quickmod(3,n-1)%mod);//注意算出3的n-1次幂,再乘以6之后一定还要再取模!
return 0;
}
我知道你还没懂,所以
已知 2^3 求 2^6, 不就是 2^3 * 2^3
快速幂就是这个原理。
遇到奇数怎么办?
那不就是 2 * 2 ^ 4 这不就成了嘛~~
所以这就是快速幂的基本思路求a ^ b
1)当b是奇数时,那么有 a^b = a * a^(b-1)
2)当b是偶数时,那么有 a^b = a^(b/2) * a^(b/2)
举个例子?2 ^10
2^10 = 2^5 * 2^5
2^5 = 2 * 2^4
2^2 = 2^1 * 2^1
2^1 = 2 * 2^0
3.这个看看他的写的,详细(手动滑稽)但是他没有我讲解的系统啦~
4.越狱
Description
监狱有连续编号为1…N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果
相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
Input
输入两个整数M,N.1<=M<=10^8,1<=N<=10^12
Output
可能越狱的状态数,模100003取余
Sample Input
2 3
Sample Output
6
HINT
6种状态为(000)(001)(011)(100)(110)(111)