Acwing222_青蛙的约会_同余方程

题目链接:https://www.acwing.com/problem/content/224/

解题思路:
对于这道题目,首先可以列出这个等式:y + n k = x + mk + Lu;
然后进行移项得到:(n - m)k - uL = x - y;
注意这里的符号,不管符号是正还是符号都可以直接套用exgcd;
需要注意的是:只有当(x - y) % (n - m, L) == 0的时候,这个方程才有解集。
对于这道题目,我们通过exgc得到k之后,我们还需要让k *= (x - y) / d;因为exgcd得到的X0针对的情况是等式的左边刚好是(a, b)的时候,所以我们需要乘上一个数;
然后这道题目要求最少的步数,其实对于方程来说就是求最小的正的x;而所有的解集:x = X0 + h(b / d);
需要注意这里的b / d可能是一个负数,但是我们在求其解集的时候是正数还是负数是没有任何影响的,因为h可以取任意的整数,由于这道题目想要求得是最小的而且是正数,所以我们需要取得b / d的绝对值,然后让 x = (x % tmp + tmp) % tmp;即可。

代码一份:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std; 

typedef long long LL;

LL xx, yy, m, n, l;

inline LL gcd(LL x, LL y) {
	return y == 0 ? x : gcd(y, x % y);
}

inline LL exgcd(LL a, LL b, LL& x, LL& y) {
	if(!b) {
		x = 1, y = 0;
		return a;
	}
	
	LL d = exgcd(b, a % b, y, x);
	y = y - a / b * x;
	
	return d;
}

int main(void) {
//	freopen("in.txt", "r", stdin);
	scanf("%lld%lld%lld%lld%lld", &xx, &yy, &m, &n, &l);
	
	if((yy - xx) % gcd(m - n, l)) puts("Impossible");
	else {
		LL x, y;
		LL d = exgcd(m - n, l, x, y);
		x *= (yy - xx) / d;
		LL tmp = abs(l / d);
		
		x = (x % tmp + tmp) % tmp;
		printf("%lld\n", x);
	} 
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章