青蛙的约会,典型拓展欧几里得
首先我们根据题意可得一个公式:X*(m-n)+Y*L=y-x
这样的话解出x,y后判断y-x是不是d的倍数,不是则无解
最终答案是 (X*(y-x)/d)%(L/d),为什么是这个答案呢。首先我们知道上面的表达式最小正整数解是X0*(y-x)/d,然后我们又知道通解就是最小正整数解加k*b/d,实际就是取模b/d,所以就是这个答案。
https://blog.youkuaiyun.com/loi_dqs/article/details/49488851
----------------------------------------------------------------------------------------------------------------------------------
更新~~今天详细看了看最小正整数解的问题。
首先,紫书上告诉的最小正整数解是x0+k*b',实际上就是(x%b+b)%b。
这个题还需要处理m和n的大小,是为了让gcd大于零,这样用上面的方法处理正整数解时不至于因为gcd是负数从而导致解还是负数。
为什么这样处理就行呢,因为余数的正负取决于n,比如n%m=p,p的正负取决于n。
#include <iostream>
#include <cmath>
#include <vector>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
ll x,y,n,m,l,X,Y;
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
ll r=ex_gcd(b,a%b,y,x);
y-=x*(a/b);
return r;
}
int main()
{
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
if(m<n)//k*L一定是正数了,这里为了保证m-n也是正数
{
swap(x,y);
swap(n,m);
}
ll d=ex_gcd(m-n,l,X,Y);
if((y-x)%d==0) printf("%lld\n",(X*((y-x)/d)%(l/d)+(l/d))%(l/d));//记得处理负数
else printf("Impossible\n");
return 0;
}