扩展欧几里得算法的模板实现
我居然现在还记不住扩欧的板子,我太弱啦!
扩展欧几里得算法解决的是这样的问题:
给定一个不定方程组ax+by=gcd(a,b),求他的一组整数解
先给出实现代码
void exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;//gcd(a,0)显然等于1*a-0*0=a
return a;
}
int ans=exgcd(b,a%b,x,y);
int tem=x;
x=y;
y-=tem-(a/b)*y;
return ans;
}
但实际正常题目是没有需要你求出一组不定方程的所有解的..而这个算法的经典应用就是求解乘法逆元
逆元:如果a*x≡1(mod p),则称a是x在模p意义下的逆元
这里的符号意思是同余,也就是说左面对p的模等于右面
显然 它可以表示成ax-1是p的整数倍
即形如:ax-py=1
那么根据上面扩展欧几里得定理的内容,我们显然可以发现只有gcd(a,p)=1,也就是互质的时候才有解,否则无解
....相信很多人看到这里其实是没懂...至少蒟蒻博主就没懂
口胡一下人话定义
如果a是x在模p意义下的逆元,那么也就相当于a是模p意义下x的倒数
上代码
#pragma GCC optimize("O2")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<limits.h>
#include<ctime>
#define N 100001
typedef long long ll;
const int inf=0x3fffffff;
const int maxn=2017;
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch>'9'|ch<'0')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return f*x;
}
int exgcd(int a,int b,int &d,int &x,int &y)
{
if(!b)
{
x=1,y=0;//gcd(a,0)显然等于1*a-0*0=a
return a;
}
exgcd(b,a%b,d,y,x);
y-=a/b*x;
}
int cal(int a,int p)
{
int d,x,y;
exgcd(a,p,d,x,y);
return d==1?(x+p)%p:-1;//如果有解直接返回范围在0到p之间的解
}
int main()
{
int a=read(),b=read();
printf("%d",cal(a,b));
}
是不是简单又整洁呢?期望时间复杂度O(ln n),编程复杂度也是很低的说x
其他求法
1.费马小定理
时间复杂度带一个log,比扩欧慢一些
2.特殊情况

转自http://blog.csdn.net/guhaiteng/article/details/52123385 其他部分也写的很棒 强烈安利
3.打表递推
适合于求范围内所有逆元
void init()
{
inv[0]=inv[1]=1;
for(int i=2;i<mod;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
以上
就让我永远不在这里写下什么有意义的话——by 吉林神犇 alone_wolf

浙公网安备 33010602011771号