POJ 1995 Raising Modulo Numbers 【Solution】(快速幂)
作者:互联网
[原题传送门](http://poj.org/problem?id=1995)
题目大意
先给定n组数据,
每组先给定m为模数,
再给定h组号码ai与bi,
输出每组数据处理的结果
题解
a^b的大小把握不住,从以下几点出发
1.考虑到求模公式:(ab)%p=(a%p)(b%p)%p
证明如下:
令a=k1p+r1,b=k2p+r2;
则(ab)%p=(k1k2pp+k1r2p+k2r1p+r1r2)%p=(r1r2)%p;
2.通过将b表示为若干指数不重复的2的次幂的和,简化计算
以下过程称为快速幂
b=\(c_{k-1}\)\(2^{k-1}\)+\(c_{k-2}\)\(2^{k-2}\)+……+\(c_{0}\)\(2^{0}\);
则\(a^b\)可以用a的不同次幂(带有2的次幂)的乘积表示
即\(a^b\)=\(a^{c_{k-1} * 2^{k-1}}\) * \(a^{c_{k-2} *2^{k-2}}\)…… *\(a^{c_{0}2^{0}}\);
再应用第1点
只需对每一项相乘取模
已知的是c的每一项数值为1或0,而b展开的每一项可以通过递推处理
代码实现如下
inline int quickm(int a,int b,int m){
int ans=1;//初始为1是因为第一步是要乘
while (b){
if (b&1) ans=(ll)ans*a%m;//b&1和b%2都可以表示其二进制下末位的值,为1则积累入答案
a=(ll)a*a%m;
}
return ans;
}
其中强制转换变量类型是为了防止两个32位整数的乘积溢出int的范围
(两个数值执行算术运算时,以参与运算的最高数值类型为基准)
总代码如下
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
inline int read(){//快读可以不用
register int x=0,f=1;
register char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();
return x*f;
}
int n,m,h;
int a,b;
inline int quickm(int a,int b,int p){
int ans=1;
for (;b;b>>=1){
if (b&1) ans=(ll)ans*a%p;
a=(ll)a*a%p;
}
return ans;
}
int main(){
n=read();
while (n--){
m=read(),h=read();
int sum1=0;
for (int i=1;i<=h;i++){
a=read(),b=read();
sum1+=quickm(a,b,m);
}
sum1%=m;
printf("%d\n",sum1);
}
return 0;
}
标签:1995,int,ll,Solution,read,while,POJ,ans,a% 来源: https://www.cnblogs.com/cancers/p/16678303.html