快速幂笔记

快速求 a b a^b ab % p 的问题

一、朴素算法 O(n* b)

思路: 对n组数据,分别循环b次后 a b a^b ab mod p

代码

#include <iostream>
using namespace std;

int main()
{
    int n;
    cin >> n;
    while(n--)
    {
	    int a,b,p;
		cin >> a >> b >> p;
		long long res = 1;
			while(b--)
				res = res *a % p;
		cout << res << endl;
    }

	return 0;
}
}

样例
2
3 2 5 – 4
4 3 9 – 1

问题 :为什么需要在每一步计算res和a时对p取余,而不是计算完res后再取余呢?
防溢出

快速幂核心思路

每一个正整数可以唯一表示为若干指数不重复的2的次幂的和

算法原理
1、 a = b ( p − 1 ) 2 p − 1 + b p − 2 2 p − 2 + . . . . . . + c 0 2 0 a=b_(p-1)^{2^{p-1}}+b_{p-2}^{2^{p-2}}+......+c_0^{2^{0}} a=b(p1)2p1+bp22p2+......+c020
2、 a 2 i = ( a 2 i − 1 ) 2 a^{2^i} = (a^{2^{i-1}})^2 a2i=(a2i1)2
3、 b&1 求出 b 在二进制表示下的最低位
4、 b >> 1 运算可以舍去最低位
注意: b&1也可以用来判断奇数和偶数,b&1=true时为奇数,反之b&1=false时为偶数

基本思路:
1、 预处理出 a 2 0 a^{2{^0}} a20, a 2 1 a^{2{^1}} a21, a 2 2 a^{2{^2}} a22, . . . , a 2 log ⁡ a^{2^{\log}} a2log
2、 遍历b在二进制表示下的所有位数pi

#include <iostream>
using namespace std;

typedef long long ll;

ll qmi(int a, int b, int p)
{
	ll res = 1 % p;
	while(b)
	{
		if(b & 1) res = res *a % p;
		a = a * (ll) a % p;
		b >>= 1;
	}
	return res;
}

int main()
{
	int n;
	scanf("%d",&n);
	while(n--)
	{
		int a,b,p;
		scanf("%d%d%d",&a,&b,&p);
		printf("%lld\n",qmi(a,b,p));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值