快速幂 | 快速积 | 矩阵快速幂 | 模板 | 斐波那契

原来我对快速幂的理解一直是错的!不是通过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 来源:CSDN
原文:https://blog.csdn.net/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;
}

作者:六小聪 来源:CSDN
原文:https://blog.csdn.net/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) 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值