1056.A ^ B Problem
Description
Input
Output
Sample Input
11 100 7
Sample Output
4
直接做
int ans = 1;
for(int i = 1;i<=b;i++)
{
ans = ans * a;
}
ans = ans % c;
这个算法的时间复杂度很大,a和b过大,很容易就会溢,找到以下公式
上面公式为下面公式的引理,即积的取余等于取余的积的取余。
快速幂算法
1.如果b是偶数,我们可以记k = a2 mod c,那么求(k)b/2 mod c就可以了。
2.如果b是奇数,我们也可以记k = a2 mod c,那么求((k)b/2 mod c × a ) mod c =((k)b/2 mod c * a) mod c 就可以了。
代码如下:
#include <cstdio>
#include <cstdlib>
#include <algorithm>
int main()
{
int ans = 1;
int a,b,c,k;
scanf("%d%d%d",&a,&b,&c);
a = a % c;
if(b%2==1)
ans = (ans * a) % c ;
k = (a*a) % c;
for(int i = 1; i<=b/2; i++)
{
ans = (ans * k) % c;
}
ans = ans % c;
printf("%d\n",ans);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当b==11时
a^11=a^(2^0+2^1+2^3)
11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 a^(2^0)*a^(2^1)*a^(2^3) ,看出来快的多了吧原来算11次,现在算三次,但是这三项貌似不好求的样子….不急,下面会有详细解释。
由于是二进制,很自然地想到用位运算这个强大的工具: & 和 >>
&运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位。还可以判断奇偶x&1==0为偶,x&1==1为奇。
>>运算比较单纯,二进制去掉最后一位。
现在已上边的式子为例:int powx(int a,int b) { int ans=1,base=a; while(b!=0) { if(b&1) ans*=base; base*=base; b>>=1; } return ans; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
base*=base;
- 1
这个是完全为了达到累乘的效果,例如上题,这个就相当于把a^11变成了a^(2^0),a^(2^1),a^(2^3);
山东省赛
另一种详细的解释:
其中要理解base*=base这一步,base*base==base^2,下一步再乘,就是base^2*base^2==base^4,然后同理 base^4*base4=base^8,,,,,see?是不是做到了base–>base^2–>base^4–>base^8–>base^16–>base^32…….指数正是 2^i 啊- #include <iostream>
using namespace std;
const int d=1000000000+7;
long long poww(long a,long b)
{
long long ans=1,base=a;
while(b!=0)
{
if(b&1)
ans=(ans*base)%d;
base=(base*base)%d;
b>>=1;
}
return ans;
}
int main()
{
long long n,m;
cin>>n>>m;
long long sum = 0;
for(int i=1;i<=n;i++)
sum = (sum+poww(i,m))%d;
cout<<sum<<endl;
return 0;
}
SDUT 3899
#include <iostream>using namespace std;
const int d=1000000000+7;
long long poww(long a,long b)
{
long long ans=1,base=a;
while(b!=0)
{
if(b&1)
ans=(ans*base)%d;
base=(base*base)%d;
b>>=1;
}
return ans;
}
int main()
{
long long n,m;
cin>>n>>m;
long long sum = 0;
for(int i=1;i<=n;i++)
sum = (sum+poww(i,m))%d;
cout<<sum<<endl;
return 0;
}