码迷,mamicode.com
首页 > 其他好文 > 详细

快速幂

时间:2020-06-24 23:24:39      阅读:47      评论:0      收藏:0      [点我收藏+]

标签:递归   多少   log   amp   fine   for   turn   进制   href   

快速幂顾名思义,就是快速算某个数的多少次幂。
其时间复杂度为O(log?N),与朴素的O(N)相比效率有了极大的提高。


核心思想就是
如果\(k\)是偶数 那么 \(x^ k =(x^{2})^{\tfrac{k}{2}}\)
如果\(k\)是奇数 那么 \(x ^ k = x * x ^{ ( k - 1 ) }\)
递归实现即可

#define LL long long
LL quickpow(LL x,LL k,LL mod)
{
	if(k==0) return 1;
	if(k&1) return x*quickpow(x,k-1,mod)%mod;
	else return quickpow(x*x%mod,k>>1,mod)%mod;
}

另一种想法就是
如果\(k\)是偶数 \(x^ k =(x^{\tfrac{k}{2}})^{2}\)
如果\(k\)是奇数 \(x ^ k = x * ( x ^{ \tfrac{k}{2}} ) ^ 2\)

LL quickpow(LL x,LL k,LL mod)
{
	if(k==0) return 1;
	LL t=q_pow(x,k>>1,mod)%mod;
	if(k&1) return ((t*t%mod)*x)%mod;
	return t*t%mod;
}

另外,如果想写(\(k\)&\(1\)\(==\) 0 的话,

? 注意& 按位与的优先级比 等号 低 ,要加括号

二进制拆分

这是最重要的一种计算方法。

\((13)_{10}=(1101)_{2}\)

\(a^{13}=a^{8}*a^{4}*a^{1}\)

也就是说,我们通过计算 \(a^{2^{i}},i \in [0,1+log_{2}k]\)

再把这些解乘起来(如果k的二进制第i位是0,就不用乘),就可以得到 \(a^{k}\)

详情见:https://www.luogu.com.cn/blog/cicos/quickpow

真的是很好的一篇题解。

Code:

LL quickpow(LL x,LL k,LL mod)
{
	LL res=1;
	while(k) {
		if(k&1) res=res*x%mod;
		x=x*x%mod; k>>=1;
	}
	return res%mod; //注意要返回res%mod,hank 1^0(mod 1)
}

但是如果把每一位预处理出来,存在 \(g[]\) 里( \(g[i]=a^{2^{i}}\) ), 就有

LL quickpow(LL x,LL k,LL mod)
{
	LL res=1;
	for(int i=0;i<=LOGK&&k;i++) {
		if(k&1) res=res*g[i]%MOD; //二进制此位为1
		k>>=1;
	} 
	return res%MOD;
}

其实写法一较为方便,

但是也有用到写法二的题(单次*复杂度高,底数相同,只要部分解)


洛谷模板题

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL b,p,k;
LL power(LL n,LL m,LL k)
{
	LL res=1LL;
	while(m) {
		if(m&1) res=(res*n)%k;
		n=n*n%k; m>>=1LL;
	}
	return res%k;
}
int main()
{
	scanf("%lld%lld%lld",&b,&p,&k);
	printf("%lld^%lld mod %lld=%lld\n",b,p,k,power(b,p,k));
	return 0;
}

快速幂

标签:递归   多少   log   amp   fine   for   turn   进制   href   

原文地址:https://www.cnblogs.com/cjl-world/p/13190482.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!