POJ1995快速幂取模

思路:因为就普通的求法把每个的幂都算出来再相加的话,数会特别大,运行速度跟内存都会消耗特别大,所以采用了快速幂取法,代码中有详细思路

-------------------------------------------------------------------------------------------------------------------------------------------------------

#include<iostream>

#include<cstdio>
#include<cstring>
#include<cstdlib>

using namespace std;

//如果不设成全局变量的话就会出错,因为这些量的值是在改变的

int ans = 0;//用来保存结果
int a = 0, b = 0;//定义底数和幂
int c = 0;//定义余数
//求a的b次方取模后的值
int Quick(int a, int b, int c)
{
int ans = 1;//定义一个用来保存该结果的变量
//(a^b)%c可以把b拆成对应的二进制,如果b的值为0,则a^b次方的位置肯定为1,所以只要关注b不为0的就可以了
//当b换成二进制后  b=b0*2^0+b1*2^1+......+bn*2^n
//a^b=a^(b0*2^0+b1*2^1+......+bn*2^n)=a^(b0*2^0)+a^(b1*2^1)+.....+a^(bn*2^n)
//只要十进制的b的值不为0就得进行运算a*a
a = a%c;//这个也可以不要,主要是避免底数过大,计算起来降低效率
while (b!=0)
{
//ans = (ans*a) % c;//因为(a*a*a*.....*a)%c=((a%c)*.....*(a%c))%c=当前的结果乘以下一个值模c的结果再模c
//设下一个a%c的值为一个常数d,则(a^b)%c的值就等于当前的值乘以下一模c的值做乘法再模c
if (b&1)//此时的b的形式为二进制,与1做与运算
{
ans = (ans*a) % c;
}
b >>= 1;//b右移一位,也就是判断b的下一个二进制位置上的值是1还是0
a = (a*a) % c;//虽然的b的二进制位上为0不用计算,但是a的值得继续往上增,因为就算b的对应位置上为0,但是b还是在继续增加
}
return ans;
}
int main()
{
int row = 0;//定义当前这组总共有多少行数据,int ans = 0;//用来保存结果
int number = 0;//定义当前总共有多少组数据
//cin >> number;
scanf("%d", &number);
while (number--)
{
ans = 0;//进行下一组数据测试时,ans应该清0
//cin >> c >> row;
scanf("%d%d", &c, &row);
//cin >> a >> b;
for (int i = 1; i <= row; i++)//对输入的每行数据进行求和
{
scanf("%d%d", &a, &b);
ans = (ans + Quick(a, b, c)) % c;//求出前一个数的余数之后加上后一个数的取余的值再取余,一直到最后一个数就能得到最终余数    
//这样是避免指数过大 而且取模易造成空间浪费
}
printf("%d\n", ans);//得到一组数据的结果
}
//cout << ans<<endl;
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值