题目描述:
输入b,p,k的值,求bp mod k的值。其中b,p,k*k为长整型数
题解:
我们要让计算机很快地求出a^b
暴力相乘的话,电脑要计算 b次。用快速幂,计算次数在 log(b) 级别,很实用。
怎么实现呢?
我们知:
(1)如果将 a 自乘一次,就会变成 a2 。再把 a2 自乘一次就会变成 a4 。然后是 a8……以此类推。
(2)axay = a(x+y)。
过程会是这样:
·假设我们拿到了 aa,并且 b = 11。想求 a11,但是又不想乘11次,有点慢。
·稍稍观察一下 b = 11,二进制下是 b = 1011。
·制作一个 base。现在 base = a,表示的是,a1 = a。
·制作一个 ans,初值 1,准备用来做答案。
while(b > 0)
{
if(b & 1)
ans *= base;
/*关于 b & 1:
x & y 是二进制 x 和 y 的每一位分别进行“与运算”的结果。
与运算,即两者都为 1 时才会返回 1,否则返回 0。
那么 b & 1
二进制
b = 1011
1 = 0001
b&1 = 0001
因为 1(二进制)的前面几位全部都是 0,
所以只有 b 二进制最后一位是 1 时,b & 1 才会返回 1。)*/
·然后 base通过自乘一次,使自己变成 a2。
base *= base;
同时
b >>= 1;
}
接着再按照以上顺序循环,以此类推。
但有时候快速幂乘的过程中会爆掉,所以我们用到快速加
原理相同,只是变一下符号。
附上代码:
#include<stdio.h> long long b,p,k; long long ksj(long long x,long long y) { long long cnt=0; while(y) { if(y%2) cnt=(cnt+x)%k; x=(x+x)%k; y/=2; } return cnt; } long long ksm(long long x,long long y) { long long cnt=1; while(y) { if(y%2) cnt=ksj(cnt,x)%k; x=ksj(x,x)%k; y/=2; } return cnt; } int main() { scanf("%lld%lld%lld",&b,&p,&k); long long ans=ksm(b,p); if(p!=0) printf("%lld^%lld mod %lld=%lld",b,p,k,ans); else printf("%lld^%lld mod %lld=0",b,p,k); }