POj 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)的一组解p0,q0后,p * a+q * b = Gcd(a, b)的其他整数解满足:
p = p0 + b/Gcd(a, b) * t
q = q0 - 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)的一组解p0,q0后,应该是
得到p * a+q * b = c的一组解p1 = p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),p * a+q * b = c的其他整数解满足:
p = p1 + b/Gcd(a, b) * t
q = q1 - 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>这是找最小正整数解:x1 = x*(b/d),则最后的解:(x1%(l/d) + l/d)%(l/d)。

        求解最小正整数解参考资料:点击打开链接

        扩展欧几里得算法实现有两种,一种是迭代法;另一种是递归,容易理解,和使用!

         迭代法:

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;
}


 

你可能感兴趣的:(poj,扩展欧几里得,1061)