解題思想:
(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就好了。