假设我们要求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),也就是a^1*a^2*a^8
看出来快的多了吧原来算11次,现在算三次,但是这三项貌似不好求的样子....不急,下面会有详细解释。 由于是二进制,很自然地想到用位运算这个强大的工具:(位运算计算)
&和>>
&运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位(因为1的二进制只有..0001,结合百科自行理解)。还可以判断奇偶x&1==0为偶,x&1==1为奇。
>>运算比较单纯,二进制去掉最后一位.
---------------------------------------------------------------------------------------------------------------------------------------
下面为自己对代码的理解,以 a^11=a(2^0+2^1+2^3)为例:
11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1
1.if(b%2)或if(b&1) r*=base;来判断二进制末尾是否有权值(1则有,0则没有),有则乘上该位置上的权值
2.base*=base; 通过累乘得到下一个位置上的权值(由最后一位转为倒数第二位,2^0转为2^1,以此类推...) 注意每一步都要执行!
3.b/2或b>>=1; 二进制去掉最后一位.如1011变为101,再返回到第一步重新计算(需注意的是此时101的末尾的1其实2^1已由第二步base的累乘得出)
来看看代码吧:
int power(int a,int b)
{
int ans=1;
while(b)
{
if(b%2)
ans*=a;
a*=a;
b/=2;
}
return ans;
}
/*int power(int a, int b) {
int ans = 1;
while (b)
{
if (b&1)
ans *= base;
a*=a;
b>>= 1;
}
return ans;
}*/
主要源于(a*b)%c=(a%c*b%c)%c;
我的理解是a^b可以看成a*a*a*a....每合并一向便可以看成新的因子,所以同时要%c
#include
#include
#include
using namespace std;
long long x,y,c;
long long power(long long a,long long b)
{
long long ans=1%c;
a=a%c;
// long long base=a;
while(b)
{
if(b%2!=0)
ans=(ans*a)%c;
a=(a*a)%c;
b/=2;
}
return ans;
}
int main()
{
cin>>x>>y>>c;
long long t=power(x,y);
cout<
要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
Input
数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。
Output
对应每组数据输出(A/B)%9973。
Sample Input
2
1000 53
87 123456789
Sample Output
7922
6060
求b的逆元用到了快速幂取模,a/b=a*(b ^ (M-2)) (mod M)
代码:
#include
#include
int power(int a,int b,int c)
{
long long ans=1,base=a%c;
while(b!=0)
{
if(b%2!=0)
ans=(ans*base)%c;
base=(base*base)%c;
b/=2;
}
return ans;
}
int main()
{
long long i,x,n,m,z;
scanf("%lld",&x);
for(i=0;i
题目:http://icpc.upc.edu.cn/problem.php?cid=1430&pid=1
题目描述
求 a 乘 b 对 p 取模的值,其中 1≤a,b,p≤10^18。
输入
第一行a,第二行b,第三行p。
输出
一个整数,表示a*b mod p的值。
样例输入
复制样例数据
2
3
9
样例输出
6
这个东西其实就是类似于快速幂(快速幂的一般写法通常称为反复平方法),这里只是将平方变为×2×2。相信理解快速幂的同学一定会明白这是什么意思吧!我直接贴个代码:
#include
#include
#include
#define ll long long
using namespace std;
const int maxn=1e5+10;
ll a,b,p;
ll power(ll a,ll b)
{
ll ans=0;
while(b)
{
if(b&1)
ans=(ans+a)%p;//注意变为+!
a=(a*2)%p;//变为*2!
b>>=1;
}
return ans;
}
int main()
{
cin>>a>>b>>p;
ll ans=power(a,b);
cout<
大数乘法几种算法:https://blog.csdn.net/frankchenfu/article/details/82259794