题目描述
求 a 的 b 次方对 p 取模的值。
输入格式
三个整数 a,b,p ,在同一行用空格隔开。
输出格式
输出一个整数,表示a^b mod p的值。
数据范围
1≤a,b,p≤109
输入样例:
3 2 7
输出样例:
2
算法1
(暴力枚举) $O(m)$
暴力枚举也就是循环一遍即可
C++ 代码
#include <iostream>
using namespace std;
#define ll long long //自定义ll为long long类型
int main()
{
ll a,b,c,ans=1;
cin>>a>>b>>c;
for (ll i=1;i<=b;i++)
ans=ans*a%c;
cout<<ans;
}
算法二
有BUG,主要是理解错误
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
#define ll long long
ll n,m,k;
ll power(ll n,ll m,ll k)
{
ll ans=1;
while(m)
{
if (m&1)
ans=ans*n%k;//如果m为奇数,则需要乘以一遍n,m降次为偶数
n=n*n%k;
ans=ans*n%k;//错误点,因为如果当前m为偶数的话,并不需要处理,只需要留到m为奇数时候处理
m>>=1;
}
return (ans%k);
}
int main()
{
cin>>n>>m>>k;
cout<<power(n,m,k);
}
正解
大致思路:我们知道,任何一个自然数都可以写成n=2^pi1+2^pi2+2^pi3+……2^pim,其中所有pi为非负整数,所以可以利用二分,将这一题次数m,转化一下即可
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
#define ll long long
ll n,m,k;
ll power(ll n,ll m,ll k)
{
ll ans=1%k;
while(m)
{
if (m&1)//如果m为奇数
ans=ans*n%k;
n=n*n%k;//将上一次的n进行平方
m>>=1;
}
return (ans%k);
}
int main()
{
cin>>n>>m>>k;
n%=k;
cout<<power(n,m,k);
}
考古
考古Orz
算法一不会超时吗
算法1会在第三个数据报错
为什么先取余再相乘?我还是有点看不懂
防止tle
点赞完毕
QwQ
爬楼点赞身体好~~~~
m>>=1是什么意思
除以2的意思
准确的说,还要取整
是哦
m&1是不是取出m的最低位与1进行与运算
m&1是判断m是否为奇数.
我觉得是这个意思,首先将a^b次方,将b用二进制表示出来,那么可以将他转换成2次幂的形式,每个二次幂相差的是a^2,二进制上有1那么就需要将最后结果乘上a,如果没有就不需要乘上a,只需将a平方,为b二进制位的前一位做准备,可能说的不是太明白,请多看几遍,或者将b转换成2进制然后将a^b转换成二次幂的形式就好懂了
暴力超时了啊
暴力当然会超时啊,我上面不是写了时间复杂度吗?QwQ
学会了快速幂了hhh多谢分享
不谢啦!
不谢啦!
暴力会报错
Time Limit Exceeded
代码运行状态: 错误数据如下所示 ×
输入
126348976 982638476 938420413
输出
标准答案
701649771
————————————————————
而且 我把这句result=result*a%p;分成两步写会直接计算错误,输出负值……
先要取模,再去相乘.不要会爆int啊
快速幂.
是的,这道题目是快速幂的模板