1. 程式人生 > >演算法複習——擴充套件歐幾里得演算法(擴充套件歐幾里得,逆元,整除)

演算法複習——擴充套件歐幾里得演算法(擴充套件歐幾里得,逆元,整除)

①歐幾里得演算法

就是求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;
}