码迷,mamicode.com
首页 > 编程语言 > 详细

扩展欧几里得算法的模板实现

时间:2017-09-15 23:49:38      阅读:374      评论:0      收藏:0      [点我收藏+]

标签:def   ffffff   algorithm   ==   print   方程组   代码   inf   符号   

我居然现在还记不住扩欧的板子,我太弱啦!

扩展欧几里得算法解决的是这样的问题:

给定一个不定方程组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),则称ax在模p意义下的逆元

这里的符号意思是同余,也就是说左面对p的模等于右面

显然 它可以表示成ax-1n的整数倍

即形如:ax-ny=1

那么根据上面扩展欧几里得定理的内容,我们显然可以发现只有gcd(a,n)=1,也就是互质的时候才有解,否则无解

#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.打表递推

适合于求范围内所有逆元

技术分享

以上

扩展欧几里得算法的模板实现

标签:def   ffffff   algorithm   ==   print   方程组   代码   inf   符号   

原文地址:http://www.cnblogs.com/tsunderehome/p/7529112.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!