高级模运算
Problem Description
人与人是不同的,有些人喜欢阅读满是女孩子的杂志,有些人喜欢在地下室引爆炸弹,而还有一些却喜欢一些麻烦的数字游戏。比如ESSE论坛的一次活动:
每个人选择两个数字Ai和Bi写在纸上,其他人不能看见。过了一段时间后,每个人说出自己纸上的数字,然后每个人的目标是求出所有的AiBi的和模M的值,最先算出结果的,就是胜利者。
作为一个程序员,你当然有办法编一个程序,以最快的速度算出结果,赢得比赛。
Input
输入包含Z组测试数据,输入第一行只包含数字Z。随后是测试数据:第一行是一个数字M(1≤M≤45000)。第二行是数字H(1≤H≤45000)表示参加游戏的人数。接下来H行,每行两个数Ai和Bi(1≤Ai,Bi≤231)。
Output
对于每组测试数据,输出以下表达式的值:
(A1B1+A2B2+...+AHBH)mod M.
Sample Input
2
16
4
2 3
3 4
4 5
5 6
36123
1
23748593029382
Sample Output
2
13195
思路:
将b以二进制存在数组中,再利用公式:
ab=a2^b0+2^b1+…+2^bk=a2^b0×a2^b1×a2^bk
其中因子递推,后项因子为前项的平方;
本题关键在于:
为防止中间结果过大溢出,应不断取模
#include<stdio.h>
long a[45004],b[45004];
int idx[34],am[34];
int abm(long a,long b,int m)
{
int i=0,j,k,p=1;
while(b)
{
idx[i++]=b%2;
b>>=1;
}
am[0]=a%m;
for(j=1; j<i; j++)
am[j]=am[j-1]*am[j-1]%m;
for(k=0; k<i; k++)
{
if(idx[k])
p=p*am[k]%m;
}
return p;
}
int main()
{
int z,m,h,i,s;
scanf("%d",&z);
while(z--)
{
scanf("%d%d",&m,&h);
for(i=0; i<h; i++)
scanf("%ld%ld",&a[i],&b[i]);
s=0;
for(i=0; i<h; i++)
s=(s+abm(a[i],b[i],m))%m;
printf("%d\n",s);
}
return 0;
}