标签:1995 int ll Solution read while POJ ans a%
[原题传送门](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
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。