power_快速幂_poj_1995_Raising Modulo Numbers

幂运算在数学上是很重要的,很多公式都涉及到了幂运算。快狠准的计算 x^y 是一项基本技能。

当然,一遍循环扫过去太慢了,<math.h> 里提供的 pow 存在精度问题且不方便取模。所以学长交了我快速幂。


快,在于减少重复计算次数。x^8 可以化成 x^4 * x^4 ,因此我们只需要计算一次 x^4 ,然后再计算 (x^4)^2 即可。

当然,如果y是奇数,可化成 x^(y/2) * x^(y/2) * x三项相乘

int ipower (int x,int y){
	int res=1;
	while (y){
		if (y&1) res*=x;
		x*=x;
		y>>=1;
	}
	return res;
}

还一种递归的可能更好理解:
int power (int x,int y){
	if (y==0) return 1;
	int res=1;
	res=power(x,y>>1);
	res*=res;
	if (y&1) res*=x;
	return res;
}

如果把 x 换成一个矩阵,* 换成矩阵乘法,power就可以变成高大上的矩阵快速幂,在递推式(如斐波拉契数列)上很有用武之地。
struct Node {
    long long  a[4][4];
};

Node multiply (Node a,Node b){ //自己写的矩阵乘法
    Node c;
    for (long long  i=0;i<4;i++){
        for (long long  j=0;j<4;j++){
          c.a[i][j]=0;
            for (long long  v=0;v<4;v++){
                c.a[i][j]+=(a.a[i][v]*b.a[v][j])%mod;
            }
            c.a[i][j]%=mod;
        }
    }
    return c;
}

Node power (Node s,long long  n){
     Node res=s;
     while (n){
        if (n&1) res=multiply(s,res);
        s=multiply(s,s);
        n>>=1;
     }
     return res;
}

poj_1995

果然递归写法还是慢一点。

(power和ipower均可AC分别是125MS和219MS);

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;

ll M,n;

ll power (ll a,ll b){
    ll res=1;
    while (b){
        if (b&1) res=(res*a)%M;
        a=(a*a)%M;
        b>>=1;
    }
    return res;
}
ll ipower (ll x,ll y){
	if (y==0) return 1;
	ll res=1;
	res=power(x,y>>1)%M;
	res=(res*res)%M;
	if (y&1) res=(res*x)%M;
	return res%M;
}

int main(){
    ll c;
    ll a[45010],b[45010],ans;
    scanf ("%I64d",&c);
    while (c--){
        ans=0;
        scanf("%I64d%I64d",&M,&n);
        for (int i=0;i<n;i++){
            scanf ("%I64d%I64d",&a[i],&b[i]);
            ans=(ans+power(a[i],b[i]))%M;
        }
        printf ("%I64d\n",ans%M);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值