POJ 1061 扩展欧几里德

这题纠结了好久,到现在才理解……

由题意可得:(n-m)t+lp=x-y,令a=n-m,b=l,d=x-y,则得:at+bp=d,令c=gcd(a,b)即与扩展欧几里德就一样了,而一般算的是ax+by=gcd(a,b),即ax+by=c,这样据算法可以求出最小的x,(从而可以求出任意解)。而本题求的是:at+bp=d,那么可以等号两边同乘d/c(在d/c除后是整数的情况下,如果不整除那就无解),即:a*t*(d/c)+b*p*(d/c)=d,这样最小的解就是t*(d/c),但是这有可能是负数,可以作如下解决……

因为a * ( t *(d / c) + b*n) + b * (p * (d / c) – a*n) = d; (n是自然数)

所以解为 (t * (d / c) % b + b) % b;

#include <iostream>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
    return !b?a:gcd(b,a%b);
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0) {x=1;y=0;return;}
    exgcd(b,a%b,x,y);
    ll t=x;x=y;y=t-a/b*y;
    /*或者如下:
    exgcd(b,a%b,y,x);
    y-=a/b*x;
    */
}
int main()
{
    ll x,y,x1,y1,m,n,l,a,b,c,d;
    cin>>x>>y>>m>>n>>l;
    a=n-m;
    b=l;
    d=x-y;
    c=gcd(a,b);
    if(d%c) {cout<<"Impossible"<<endl;return 0;}
    exgcd(a,b,x1,y1);
    x1=(x1*(d/c)%b+b)%b;
    cout<<x1<<endl;
    return 0;
}


你可能感兴趣的:(POJ 1061 扩展欧几里德)