幂运算在数学上是很重要的,很多公式都涉及到了幂运算。快狠准的计算 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;
}
果然递归写法还是慢一点。
(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;
}