快速幂
可以快速求在O(log \(k\))复杂度下出 \(a^{k}\)mod \(p\) 的结果($1\leq a,p,k\leq 10^{9} $)
如果是n组数据,时间复杂度就是O(\(n * log k\))
基本思路
1.先预处理出来\(a^{2^{0}},a^{2^{1}},...,a^{2^{logk}}\)这k个数
2.将\(a^{k}\)用\(a^{2^{0}},a^{2^{1}},...,a^{2^{logk}}\)这k个数来组合,即组合出\(a^{k}\) = \(a^{2^{x1}}*a^{2^{x2}}*...*a^{2^{xt}}\) = \(a^{2^{x1}+2^{x2}+...+2^{xt}}\)
ps: 为什么 \(k\) 可以用 \({2^{0}},{2^{1}},{2^{2}},...{2^{logk}}\) 中的数凑出来?
答: \(2^{{log_{2}}k} = k\) 所以一定可以凑出k
如何组合出\(a^{k}\)
将k看成二进制形式
如果最后一位为1则乘上当前位的权,并将权乘个a倍变成下一个位的权
例子:凑$a^{5}$,5写为二进制为101
1.最后一位为1,此位权为\(a^{2^{0}}\),res = 1*\(a^{2^{0}}\),将权改成a倍变成下一位权\(a^{2^{1}}\),将二进制数101最后一位去掉变成二进制数10
2.最后一位为0,此位权为\(a^{2^{1}}\),res = 1*\(a^{2^{0}}\)不变,将权改成a倍变成下一位权\(a^{2^{2}}\),将二进制数10最后一位去掉变成二进制数1
3.最后一位为1,此位权为\(a^{2^{2}}\),res = 1*\(a^{2^{0}} * a^{2^{2}}\),将权改成a倍变成下一位权\(a^{2^{3}}\),将二进制数10最后一位去掉变成二进制数1
所以 res = \(a^5\) 就可以计算出来
注意
凡是中间结果可能会溢出的地方,都要特殊处理:
1.快速幂的结果都要开long long,快速幂计算过程中res和权要开long long
2.可能溢出的地方(res、权)都要取模
代码
#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 = (LL)a * a % p; // 这里要开LL
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));
}
return 0;
}
标签:二进制,res,LL,long,一位,int,快速 来源: https://www.cnblogs.com/rdisheng/p/16591141.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。