欧几里得:求a,b最大公约数的辗转相除法
扩展欧几里得:一定存在x,y使得 a*x+b*y = gcd(a,b)成立
证明见 http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 这个博客
题意:(n-m) *t + L *p = x-y 设 a= n-m ,b=L ,x-y=c ,gcd(a,b) =d 求使之成立的非负最小 t或者直接说不成立输出impossible
变成a*t + b *p = c
扩展欧几里得:a*t0 + b*p0 = d
a整除d,b整除d,所以c必须整除d,不然就。。输出impossible
c整除d时,上式都*(c/d) 得题目要求的式子。。
先求出一个 t0 的解
a*t1 + b*p1 = d
a*t2 + b*p2 =d
t1 - t2 = b (p2-p1)/a
p2 - p1 一定是a/d的倍数
b(p2-p1)/a一定是b/d的倍数
t0之间每组相差 b/d ,每次加或减就行了
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
#define FOR(i,j,k) for(int i =j; i<=k ;i++)
#define ll long long
const int maxn =50;
ll t,p,d;
ll gcd(ll a,ll b)
{
return b == 0? a: gcd(b,a%b);
}
void exgcd(ll a,ll b)
{
if( b == 0)
{
t = 1;
p = 0;
d = a;//d=gcd(a,b)
}
else{
exgcd(b ,a % b);
int x = t;
t = p;
p = x-a/b *p;
}
}
int main()
{
ll n,m,l,x,y;
while(~scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &l))
{
bool flag = 0;
ll a = n-m, b= l,c = x-y;
//if(m == n) flag =1;
exgcd(a,b);
if(c % d != 0)
flag =1;
if(flag)
cout<<"Impossible"<<endl;
else{
ll v = t*c/d;
cout<<(v% (b/d) + b/d)%(b/d)<<endl;
}
}
return 0;
}