算法复习——扩展欧几里得算法(扩展欧几里得,逆元,整除)

①欧几里得算法

就是求gcd的有趣的辗转相除法,不再赘述啦0v0

代码:

int gcd(int a,int b)
{
	if(b==0)
		return a;
	else return gcd(b,a%b);
}

②扩展欧几里得算法

需要解决这样的问题:两个非0整数a,b,求一组整数解(x,y),使得ax+by=gcd(a,b).

(PS:证明之后补上0....0)

int exgcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	int g=exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
	return g;
}

③求逆元

可以解决这样的问题:设a和m是整数,求a模m的逆元(逆元:设abm都是整数,m>1,有ab模m和1模m相等,它们拥有相同的余数,那么ab互为模m的逆元。也就是说,有两个数的乘积,如果模m后等于1,则它们互为m的逆元)。

gcd(a,m)=1有解。

即求ax+my=1=gcd(a,m)。

代码:

ll inverse(ll a,ll m,ll c)
{
	ll x,y;
	ll g=exgcd(a,m,x,y);
	if(c%g!=0)
		return -1;
	 x*=c/g;
     m/=g;
     if(m<0)
		 m=-m;
    ll ans=x%m;
    if(ans<=0)
		ans+=m;
    return ans;
}

接下来给几个例子0V0↓

例子1:zoj 3609,传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4712

题意:输入一个n,给n组a和m,求每组a模m的最小逆元。

吐槽:m=1的情况……窒息了

代码:

//zoj 3609求最小逆元
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;

int gcd(int a,int b)
{
	if(b==0)
		return a;
	else return gcd(b,a%b);
}

int exgcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	int g=exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
	return g;
}

int inverse(int a,int m)
{
	int x,y;
	int g=exgcd(a,m,x,y);
	return (x%m+m)%m;
}

int main()
{
	int a,m,n,x,y;
	cin>>n;
	while(n--)
	{
		cin>>a>>m;
		int ans=exgcd(a,m,x,y);
		if(m==1)
		{
			cout<<1<<endl;
			continue;
		}
		if(ans!=1)
			cout<<"Not Exist"<<endl;
		else
		{
			x%=m;
			if(x<0)
				x=(x%m+m)%m;
			cout<<x<<endl;
		}
	}

	return 0;
}

例子2:hdu 1576,传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1576

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;

int gcd(int a,int b)
{
	if(b==0)
		return a;
	else return gcd(b,a%b);
}

int exgcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	int g=exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
	return g;
}

int inverse(int a,int m)
{
	int x,y;
	int g=exgcd(a,m,x,y);
	return (x%m+m)%m;
}

int main()
{
	int t,n,b;
	cin>>t;
	while(t--)
	{
		cin>>n>>b;
		int m=9973;
		int ans=inverse(b,m);
		ans=ans*n%m;
		cout<<ans<<endl;
	}
	return 0;
}

例子3:hdu2668,传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2669

模板题0V0

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;

ll gcd(ll a,ll b)
{
	if(b==0)
		return a;
	else return gcd(b,a%b);
}

ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	ll g=exgcd(b,a%b,x,y);
	ll t=x;
	x=y;
	y=t-a/b*y;
	return g;
}

ll inverse(ll a,ll m)
{
	ll x,y;
	ll g=exgcd(a,m,x,y);
	return (x%m+m)%m;
}

int main()
{
	ll a,m,x,y;
	while(scanf("%lld %lld",&a,&m)!=EOF)
	{
		ll ans=exgcd(a,m,x,y);
		if(ans!=1||m==1)
			cout<<"sorry"<<endl;
		else
		{
			x%=m;
			if(x<0)
				x=(x%m+m)%m;
			cout<<x<<" "<<(1-a*x)/m<<endl;
		}
	}
	return 0;
}

例子4:poj1061,传送门:http://poj.org/problem?id=1061

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;

ll gcd(ll a,ll b)
{
	if(b==0)
		return a;
	else return gcd(b,a%b);
}

ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	ll g=exgcd(b,a%b,x,y);
	ll t=x;
	x=y;
	y=t-a/b*y;
	return g;
}

ll inverse(ll a,ll m,ll c)
{
	ll x,y;
	ll g=exgcd(a,m,x,y);
	if(c%g!=0)
		return -1;
	 x*=c/g;
     m/=g;
     if(m<0)
		 m=-m;
    ll ans=x%m;
    if(ans<=0)
		ans+=m;
    return ans;
}

int main()
{
	ll a,b,x,y,l;
	while(scanf("%lld %lld %lld %lld %lld",&x,&y,&a,&b,&l)!=EOF)
	{
		ll ans=inverse(a-b,l,y-x);
		if(ans==-1)
			cout<<"Impossible"<<endl;
		else
			cout<<ans<<endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
扩展欧几里算法是一种求解线性同余方程 ax ≡ 1 (mod m) 中 x 的元的方法。元是指数值 x 使得 ax 与 m 取模之后的结果为 1。 下面是一个用 Java 实现扩展欧几里算法元的代码示例: ```java public class InverseElement { public static int extendedEuclidean(int a, int b) { int[] coeffs = new int[3]; // 存储扩展欧几里算法求解的系数 int x = 0, y = 0; while (b != 0) { coeffs = updateCoeffs(a, b, coeffs); a = coeffs[0]; b = coeffs[1]; x = coeffs[2]; y = coeffs[3]; } if (a == 1) { return (x % m + m) % m; // 防止结果为负数 } else { return -1; // 没有元 } } private static int[] updateCoeffs(int a, int b, int[] coeffs) { if (b == 0) { coeffs[0] = a; coeffs[1] = b; coeffs[2] = 1; coeffs[3] = 0; return coeffs; } coeffs = updateCoeffs(b, a % b, coeffs); int x1 = coeffs[2]; int y1 = coeffs[3]; coeffs[2] = y1; coeffs[3] = x1 - (a / b) * y1; return coeffs; } public static void main(String[] args) { int a = 7; int m = 11; int inverse = extendedEuclidean(a, m); System.out.println("元: " + inverse); } } ``` 在上述代码中,`extendedEuclidean` 方法实现了扩展欧几里算法, `updateCoeffs` 方法用于更新系数, `main` 方法用于测试求元的结果。在示例中,我们以 `a = 7` 和 `m = 11` 为例来求解元。 按照扩展欧几里算法的步骤,我们递归调用 `updateCoeffs` 方法来更新系数,直到 b 为 0。然后,如果 a 为 1,则返回取模后的 x 值作为元;否则,返回 -1 表示没有元。 输出结果为:元:8,表示在模 11 下,7 的元为 8。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值