原来我对快速幂的理解一直是错的!不是通过t = b*m把at写成abm从而让惩罚次数由b * m变为b+m!而是利用了二进制!
(a*b)modc = b * (amodc)
从而推出公式
当b为偶数时:a^b mod c = ((ab/2)2) mod c
当b为奇数时:a^b mod c = ((ab/2)2× a) mod c
#include <bits/stdc++.h>
using namespace std;
//简单来说就是把b当成2进制形式,然后累加;
// 2*7=2*(1*2^0+1*2^1+1*2^2)=2*1*2^0+2*1*2^1+2*1*2^2;
long long FastMul(long long a,long long b) //快速积 a*b
{
long long ans=0;
while(b){
if(b&1) //二进制数b各位如果为1
ans+=a;
a+=a;
b>>=1; //右移1位,相当于除以2
}
return ans;
}
long long FastExp(long long a,long long b) //快速幂 a^b
{
long long ans=1;
while(b){
if(b&1)
ans*=a;
a*=a;
b>>=1;
}
return ans;
}
//快速积取模简单来说就和上面说明一样,只是每次多一个取余过程,下次运算加上上次的余数;
// 2*7%5=2*(1*2^0+1*2^1+1*2^2)%5=(2*1*2^0%5+2*1*2^1%5+2*1*2^2%5)%5 (不知道是不是这样表达的,嘻嘻)
long long FastMulMod(long long a,long long b,long long c) //快速积取模 a*b%c
{
long long ans=0;
while(b){
if(b&1)
ans=(ans+a)%c;
a=(a+a)%c;
b>>=1;
}
return ans;
}
long long FastExpMod(long long a,long long b,long long c) //快速幂取模 a^b%c
{
long long ans=1;
while(b){
if(b&1)
ans=(ans*a)%c;
a=(a*a)%c;
b>>=1;
}
return ans;
}
int main()
{
printf("%ld\n",FastMul(100,100));
printf("%ld\n",FastExp(2,10));
printf("%ld\n",FastMulMod(3,93,5));
printf("%ld\n",FastExpMod(2,9,5));
return 0;
}
作者:临渊703 来源:优快云
原文:https://blog.youkuaiyun.com/linyuan703/article/details/82350284
版权声明:本文为博主原创文章,转载请附上博文链接!
long long Mode(long long a, long long b, long long mode)
{
long long sum = 1;
a = a % mode;
while (b > 0) {
if (b % 2 == 1) //判断是否是奇数,是奇数的话将多出来的数事先乘如sum
sum = (sum * a) % mode;
b /= 2;
a = (a * a) % mode;// 不断的两两合并再取模,减小a和b的规模
}
return sum;
}
作者:六小聪 来源:优快云
原文:https://blog.youkuaiyun.com/dbc_121/article/details/77646508
版权声明:本文为博主原创文章,转载请附上博文链接!
矩阵快速幂 原博
const int MOD=10000;
struct mat
{
int a[2][2];//这里数据范围就用小的示范
};
mat mat_mul(mat x,mat y)//实现两个矩阵相乘,返回的还是一个矩阵。
{
mat res;//用来表示得到的新的矩阵;
memset(res.a,0,sizeof(res.a));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
{
res.a[i][j]+=x.a[i][k]*y.a[k][j];
res.a[i][j]%=MOD;//这一步看题目具体需要了
}
return res;
}
int pow(int n)//还是小范围数据来说吧,要不然返回值的类型自己定义
{
mat c,res;
memset(res.a,0,sizeof(res.a));
c.a[0][0]=1;//给矩阵赋初值
c.a[0][1]=1;
c.a[1][0]=1;
c.a[1][1]=0;
for(int i=0;i<n;i++) res.a[i][i]=1;//单位矩阵;
while(n)
{
if(n&1) res=mat_mul(res,c);//这里看就要用到上面的矩阵相乘了;
c=mat_mul(c,c);
n=n>>1;
}
return res.a[0][1];
}//时间复杂度log(n)