power_快速幂_poj_1995_Raising Modulo Numbers

来源:互联网 发布:centos7下nginx配置 编辑:程序博客网 时间:2024/05/15 22:27

幂运算在数学上是很重要的,很多公式都涉及到了幂运算。快狠准的计算 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
原创粉丝点击