其他分享
首页 > 其他分享> > POJ 1995 Raising Modulo Numbers 【Solution】(快速幂)

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