小白快速了解快速幂法和逆元法以及使用
我之前没学过快速幂法和逆元法,写过这题才知道。新手上路慢慢来!我来说下我的理解。
快速幂法:我们知道求 a^b%N,当b很大的时候需要经过很多运算,快速幂让计算时间大大减少。我们把b转化为多个2的幂次方,首先我们需要知道一个数取模的运算:
a*b%N=(a%N)*(b%N) (b+a)%N=b%N+a%N.......除了除法不能直接模外,其他的和普通的运算差不多
除法不能直接取模需要用逆元法!!!
如:b=13:13=1101(2),,所以b=2^0+2^2+2^3;
本来需要计算13次现在只需要计算3次就能算出答案:下面是快速幂的代码:
long long q_power(long long a,long long b)//a^b 记得%N
{
long long ans=1;
while(b)
{
if(b&1)//b的二进制的最后一位是1
{
ans=ans*a%N;
}
a=a*a%N;//依次求次方,但是不能超过模
b>>=1;//把b的二进制的往前移动,去掉已经计算过的那位数
}
return ans;
}
每次记得取模(看情况而定取不取模,这题需要取)
PS:这种方法N也就是要模的数必须是质数!!!,这很重要。
接下就是逆元法了,解决除法取模的情况,应用逆元法把除法变成乘法:
首先你要知道费马小定理:
1.a和N的最大公约数是1,gcd(a,N)=1;//N就是我们需要模的数
2.a^(N-1)%N=1;//费马小定理,自行百度,我只知道用。
3.简单的变形:
a^(N-1)%N=1
a^(N-2)*a%N=1
a^(N-2)%n=1/a
所以我们可以把除法变成乘法: 1/a = a^(N-2)%N
知道这些我们就可以去AC了
#include<stdio.h>
#define N 1000000007
/**
1.快速幂法
2.逆元法》》把除数的模变成可以模的
*/
long long q_power(long long a,long long b)//a^b 记得%N
{
long long ans=1;
while(b)
{
if(b&1)//b的二进制的最后一位是1
{
ans=ans*a%N;
}
a=a*a%N;//依次求次方,但是不能超过模
b>>=1;//把b的二进制的往前移动,去掉已经计算过的那位数
}
return ans;
}
int main()
{
long long m,n;
scanf("%lld",&n);
//* a1*(q^(n+1)-1)/2 等比数列公式,然后把2进行逆元*/
m=(q_power(3,n+1)-1);
n=q_power(2,N-2);
printf("%lld\n",(m*n)%N);
return 0;
}
用拓展欧几里得求逆元的方法:拓展欧几里得求逆元