快速幂运算详解

简介

快速幂很重要哦,当幂是long longlong~longlong long级别时(这也要用latex我是不是疯了 ),用快速幂可以将复杂度降到log级别。快速幂的重要应用就是求逆元啦(我只知道这个),下面简单介绍一下求逆元的原理。
由费马小定理:
ap−1≡ 1 (mod  p)a^{p-1}\equiv~1~(mod~~p)ap1 1 (mod  p) (ppp是素数且(a,p)=1(a,p)=1(a,p)=1)
于是就有
ap−2≡ a−1 (mod  p)a^{p-2}\equiv~a^{-1}~(mod~~p)ap2 a1 (mod  p)
然后快速幂就可以求a mod p 意义下的逆元a−1a~mod~p~意义下的逆元a^{-1}a mod p a1了(当然 p ~p~ p 要是素数)

好了进入正题

怎么求 a=b p (mod  k)a = b^{~p}~(mod~~k)a=b p (mod  k)呢?
既然复杂度是log级别了,自然是把p拆成二进制啦,其实就是处理出b1,b2,b4,b8,b16...b^1,b^2,b^4,b^8,b^{16}...b1,b2,b4,b8,b16...,然后找机会相乘一下就得了

举个例子

要求35, p=5, p=22+203^5,~p=5,~p=2^2+2^035, p=5, p=22+20, 也就是求320+223^{2^0+2^2}320+22,即是31∗34,{3^1}*{3^4},3134,  p~~p  p用二进制表示成101101101,我们从最右边开始扫,每次右移一位,遇到第 x ~x~ x 位为 1 ~1~ 1 的时候就乘上 b2x~b^{2^x} b2x, 至于 b2x~b^{2^x} b2x,每次右移的时候让 b ~b~ b 乘自己就可以了。
在这个例子中
ans=1,b=31=3,此时p第0位为1,于是ans=ans∗b, ans=3,b=3∗3=32=9ans=1, b=3^1=3, 此时p第0位为1,于是ans = ans*b, ~ans = 3, b = 3*3=3^2=9ans=1,b=31=3,p01ans=ansb, ans=3,b=33=32=9;
ans=3,b=32=9,此时p第1位为0,ans=3,b=9∗9=34=81ans=3, b=3^2=9, 此时p第1位为0,ans = 3, b = 9*9 = 3^4=81ans=3,b=32=9,p10ans=3,b=99=34=81
ans=3,b=34=81,此时p第2位为1,ans=ans∗b, ans=243ans=3,b=3^4=81,此时p第2位为1,ans=ans*b,~ans=243ans=3,b=34=81,p21ans=ansb, ans=243
懂吧,因为5=1+45=1+45=1+4,我们处理得到了31,32,34,38...3^1,3^2,3^4,3^8...31,32,34,38...,该相乘的时候相乘就行了。
下面贴代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#define LL long long
using namespace std;
LL ksm(LL b, LL p, LL k){
	LL s = 1;
	while(p){
		if(p & 1) s = s * b % k;
		b = b * b % k;
		p >>= 1;
	}
	return s % k;
}
int main(){
	int i, j, n, m;
	LL b, p, k;
	scanf("%lld%lld%lld", &b, &p, &k);
	printf("%lld^%lld mod %lld=%lld", b, p, k, ksm(b, p, k));
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值