解题思想:
(x + step * m) % L = (y + step * n) % L
则(x - y + step * (m - n) ) % L == 0 || ( y - x + step * (n - m)) % L == 0
则(x - y + step * (m - n) ) = p * L || ( y - x + step * (n - m)) = p * L
若m > n则相当于求 step * (m - n) + p * L = y - x 的整数解,其中step和p为变元
同理:若m < n相当于求 step * (n - m) + p * L = x - y 的整数解,其中step和p为变元
因此问题转化为求数论中求解二元一次不定方程的整数解问题,具体参考,陈景润写的初等数论1第3章。
所谓的欧几里德扩展算法:
107 * x + 37 * y = 1的一个整数解,求解过程如下:
代码:
#include <iostream>
#include <cstdio>
using namespace std;
#define ABS(a) (a<0)?(-a):(a)
long long gcd(long long a,long long b)//求a,b的最大公约数,a,b为正
{
//a = k*b + r, r = a%b
if (b == 0)return a;
if(a < b)swap(a,b);
return gcd(b,a%b);
}
//对应于上述,图片中的求解过程
long long exgcd(long long a,long long b,long long &s,long long &t)//s是a的系数,t是b的系数
{
//a = k*b + r, r = a%b
if (b == 0)
{
s = 1,t = 0;
return a;
}
long long r = exgcd(b,a%b,s,t);
long long k = s;
s = t;
t = k-a/b*t;
return r;
}
int main()
{
freopen("in.txt","r",stdin);
long long x,y,m,n,L;
while (cin>>x>>y>>m>>n>>L)
{
if(m == n)
{
cout<<"Impossible"<<endl;
continue;
}
long long a = m - n, b = L;//b > 0
long long c = y - x;
if(a < 0)a = -a, c = -c;
//a,b都大于0
//问题转化为求解a*xx + b*yy = c的整数解
long long r = gcd(a,b);
if (c%r)//若不能整除,没有整数解
{
cout<<"Impossible"<<endl;
continue;
}
a /= r,b /= r, c/= r;//消去公因数,使a,b互质
long long s,t;
exgcd(a,b,s,t);
long long xx = c*s;
xx %= b;
while(xx < 0)
xx += b;
cout<<xx<<endl;
}
}
这一题wrong answer的n次,最后才发现数据类型一直用的是int,一定是加减法时越界了。全部改成long long就好了。