POj 1061カエルのデート
3096 ワード
拡張ユークリッド:
拡張ユークリッドを用いて,不定方程式を解いた.例えば、p*a+q*b=c<1>の不定方程式(a,b,cが既知)については、拡張ユークリッドアルゴリズムで解くことができる.<1>式については、解があれば、必ず以下のものがある.
gcd(a,b)/c = 0;
拡張ユークリッドアルゴリズムを用いて不定方程式を解決する方法
不定整数方程式pa+qb=cの場合、c mod Gcd(a,b)=0の場合、その方程式には整数解が存在し、そうでなければ整数解は存在しない.
p*a+q*b=Gcd(a,b)の解p 0,q 0のセットが見つかった後、p*a+q*b=Gcd(a,b)の他の整数解は、以下のように満たされる整数解を探す方法を上述した.
p = p0 + b/Gcd(a, b) * t
q=q 0-a/Gcd(a,b)*t(ここでtは任意の整数)
pa+qb=cの整数解については,p*a+q*b=Gcd(a,b)の各解にc/Gcd(a,b)を乗せればよい.
p*a+q*b=Gcd(a,b)の解p 0,q 0のセットが見つかった後、
p*a+q*b=cの解p 1=p 0*(c/Gcd(a,b)),q 1=q 0*(c/Gcd(a,b)),p*a+q*b=cの他の整数解が得られた.
p = p1 + b/Gcd(a, b) * t
q=q 1-a/Gcd(a,b)*t(ここでtは任意の整数)
p,qはp*a+q*b=cのすべての整数解である.
ここでは、(n-m)*t+k*l=x-y;
a=n-m;b = x- y;本題はa*t+k*l=b方程式tを満たす最小値を解くことであり、一次同余方程式a*t=b(mod l)の最小正整数解を求めることである.
手順:
<1>方程式a*t+k*l=bを書き出し,拡張ユークリッドEx_を利用する.EucGcd(Long long a,Long long l,Long long&x,Long long&y)は、最大公約数dを求める.
<2>解があるかどうかを判断し、b%d==0、解があり、解は存在するが唯一ではない!
<3>これは最小正の整数解を探す:x 1=x*(b/d)であり、最後の解:(x 1%(l/d)+l/d)%(l/d)である.
解の最小の正の整数解の参考資料を求めます:クリックしてリンクを開けます
拡張ユークリッドアルゴリズムの実現には2つあり、1つは反復法である.もう一つは再帰的で、理解しやすく、使いやすい!
反復法:
再帰:
次は1061のコードです.
拡張ユークリッドを用いて,不定方程式を解いた.例えば、p*a+q*b=c<1>の不定方程式(a,b,cが既知)については、拡張ユークリッドアルゴリズムで解くことができる.<1>式については、解があれば、必ず以下のものがある.
gcd(a,b)/c = 0;
拡張ユークリッドアルゴリズムを用いて不定方程式を解決する方法
不定整数方程式pa+qb=cの場合、c mod Gcd(a,b)=0の場合、その方程式には整数解が存在し、そうでなければ整数解は存在しない.
p*a+q*b=Gcd(a,b)の解p 0,q 0のセットが見つかった後、p*a+q*b=Gcd(a,b)の他の整数解は、以下のように満たされる整数解を探す方法を上述した.
p = p0 + b/Gcd(a, b) * t
q=q 0-a/Gcd(a,b)*t(ここでtは任意の整数)
pa+qb=cの整数解については,p*a+q*b=Gcd(a,b)の各解にc/Gcd(a,b)を乗せればよい.
p*a+q*b=Gcd(a,b)の解p 0,q 0のセットが見つかった後、
p*a+q*b=cの解p 1=p 0*(c/Gcd(a,b)),q 1=q 0*(c/Gcd(a,b)),p*a+q*b=cの他の整数解が得られた.
p = p1 + b/Gcd(a, b) * t
q=q 1-a/Gcd(a,b)*t(ここでtは任意の整数)
p,qはp*a+q*b=cのすべての整数解である.
ここでは、(n-m)*t+k*l=x-y;
a=n-m;b = x- y;本題はa*t+k*l=b方程式tを満たす最小値を解くことであり、一次同余方程式a*t=b(mod l)の最小正整数解を求めることである.
手順:
<1>方程式a*t+k*l=bを書き出し,拡張ユークリッドEx_を利用する.EucGcd(Long long a,Long long l,Long long&x,Long long&y)は、最大公約数dを求める.
<2>解があるかどうかを判断し、b%d==0、解があり、解は存在するが唯一ではない!
<3>これは最小正の整数解を探す:x 1=x*(b/d)であり、最後の解:(x 1%(l/d)+l/d)%(l/d)である.
解の最小の正の整数解の参考資料を求めます:クリックしてリンクを開けます
拡張ユークリッドアルゴリズムの実現には2つあり、1つは反復法である.もう一つは再帰的で、理解しやすく、使いやすい!
反復法:
Long long Ex_EucGcd(Long long n, Long long m, Long long &x, Long long &y) {
Long long x1 = 1, x2 = 0, x3 = n;
Long long y1 = 0, y2 = 1, y3 = m;
while (x3 % y3 != 0) {
Long long d = n / m;
Long long t1, t2, t3;
t1 = x1 - d * y1; t2 = x2 - d * y2; t3 = x3 - d * y3;
x1 = y1; x2 = y2; x3 = y3;
y1 = t1; y2 = t2; y3 = t3;
};
x = y1; y = y2;
return y3;
}
再帰:
long long Extended_Gcd(long long a, long long b, long long &x, long long &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
long long d = Extended_Gcd(b, a%b, x, y);
long long t = x - a/b * y;
x = y;
y = t;
return d;
}
次は1061のコードです.
#include <iostream>
using namespace std;
long long Extended_Gcd(long long a, long long b, long long &x, long long &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
long long d = Extended_Gcd(b, a%b, x, y);
long long t = x - a/b * y;
x = y;
y = t;
return d;
}
int main()
{
long long x, y, n, m, l;
long long a,b,c;
long long x1,y1;
while(cin>>x>>y>>m>>n>>l)
{
a = n - m;
b = l;
c = x - y;
long long M = Extended_Gcd(n-m, l, x1, y1);
if( (c%M != 0) || (m == n) )
cout<<"Impossible"<<endl;
else
{
long long s;
s = b/M;
x1 = x1 * ( c/M );
x1 = (x1%s + s )%s;
cout<<x1<<endl;
}
}
return 0;
}