快速幂学习(代码解释更详细)

1.目的:快速求出

的结果 O(logk)

暴力算法:

2.思路:反复平方法

 把k化成二进制

例如:4的5次方mod 10

先算出:

在把5化成二进制101,

通过查询上面的数据代入:得出结果4;

题目:

给定 nn 组 ai,bi,piai,bi,pi,对于每组数据,求出 abiimodpiaibimodpi 的值。

输入格式

第一行包含整数 nn。

接下来 nn 行,每行包含三个整数 ai,bi,piai,bi,pi。

输出格式

对于每组数据,输出一个结果,表示 abiimodpiaibimodpi 的值。

每个结果占一行。

数据范围

1≤n≤1000001≤n≤100000,
1≤ai,bi,pi≤2×1091≤ai,bi,pi≤2×109

输入样例:

2
3 2 5
4 3 9

输出样例:

4
1

代码:

#include<iostream>
#include<algorithm>

using namespace std;
// |和& 都是按位
typedef long long LL;

/*
int qmi(int a,int b,int c)
{
    int ans=1;
    while(b){
        if(b%2==1)  //判断指数是奇数还是偶数
        {
            ans=ans*a;    将ans乘a
            a=a*a;   将底数平方
            b=b/2;   指数除以2
            例如:3^10=(3^2)^5=9^5=9*9^4=9*(81)^2=9*(81^2)^1;
        }
        else   //如果是偶数的话直接将底数平方指数除以2
        {
            a=a*a;
            b=b/2;
        }
    }
}
以上还没有取模,因此以上对ans=ans*a%c;a=a*a%c才算结束,从哪里取模都是一个效果

以下是对以上过程的简单写法
*/

LL qmi(LL a,LL k,LL p){
    LL res=1;
    while(k)  //对k二进制化,从低位到高位
    {
        //如果
        if(k&1) res=(LL) (res*a)%p;
        k>>=1;
        a=(LL) (a*a)%p;  
    }
    return res;
}

int main  () {
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,k,p;
        scanf("%d%d%d",&a,&k,&p);
        cout << qmi(a,k,p)<< endl;
    }
    return 0;
}

代码2:

#include<iostream>

using namespace std;

typedef long long ll;

ll ksm (ll a,ll b,ll c)
{
	if(b==0) return 1%c;  //出口
	ll ans;
	if(b%2==0) //偶数
	{
		ll now =ksm(a,b/2,c);
		ans=(now*now)%c; 
	} 
	else
	{
		ll now = ksm (a,b/2,c);
		ans=(now*now%c)*a%c;
	}
	return ans;
}

int main() {
ll a,b,c;
cin>>a>>b>>c;

cout<<ksm(a,b,c);
	
	
	return 0;
}

快速乘和快速幂
#include<iostream>

using namespace std;

typedef long long ll;
//快速幂的扩展  :a,b,c<=10^18
//数论知识:(a+b)%c==((a%c)+(b%c))%c 
//			(a*b)%c==((a%c)*(b%c))%c
ll chengfa (ll a,ll b,ll c)//快速乘实现a*b 
{
	ll ans;
	if(b==0) return 0;  //a*0
	if(b%2==0)  
	{
		ll now =chengfa(a,b/2,c);
		ans=(now+now)%c;
	}
	else 
	{
		ll now=chengfa(a,b/2,c);
		ans=(((now+now)%c)+a%c)%c;
	}
	return ans;

}

ll ksm_up(ll a,ll b,ll c)
{
	ll ans;
	if(b==0) return 1%c;
	if (b%2==0)
	{
		ll now =ksm_up(a,b/2,c);
		ans=chengfa(now,now,c);
	}
	else
	{
	 ll now =ksm_up(a,b/2,c);
	 ans=chengfa(chengfa(now,now,c),a,c);
	}	
	
	return ans;	
} 

//快速幂 
ll ksm (ll a,ll b,ll c)
{
	if(b==0) return 1%c;  //出口
	ll ans;
	if(b%2==0) //偶数
	{
		ll now =ksm(a,b/2,c);
		ans=(now*now)%c; 
	} 
	
	else
	{
		ll now = ksm (a,b/2,c);
		ans=(now*now%c)*a%c;
	}
	return ans;
}

int main() {
ll a,b,c;
int n;
cin>>n;
while(n--)
{
	cin>>a>>b>>c;
cout<<ksm_up(a,b,c)<<endl;
}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值