青蛙的约会【同余】【扩欧】

>Link

luogu P1516


>Description

求关于 t t t的同余方程 x + t n ≡ y + t m ( m o d L ) x+tn\equiv y+tm(modL) x+tny+tm(modL)


>解题思路

把常数和未知数分开: t n − t m ≡ y − x ( m o d L ) tn-tm\equiv y-x(modL) tntmyx(modL)
然后同余转换成等式:
t n − t m + s L = y − x tn-tm+sL=y-x tntm+sL=yx
t ( n − m ) + s L = y − x t(n-m)+sL=y-x t(nm)+sL=yx
t , s t,s t,s都是未知数,现在就是如 a x + b y = c ax+by=c ax+by=c 的式子

为使得 a , b a,b a,b 互质(就可以用扩欧求了), a , b a,b a,b 同除以 g c d ( a , b ) gcd(a,b) gcd(a,b),那等式右边的 c c c 也需要除以 ( a , b ) (a,b) (a,b)。如果 c c c 不能整除 ( a , b ) (a,b) (a,b),就说明无解了。
g = g c d ( a , b ) g=gcd(a,b) g=gcd(a,b),现在求 a g x + b g y = c g \frac a gx+\frac b gy=\frac c g gax+gby=gc
a g , b g \frac a g,\frac b g ga,gb 已互质,用扩展欧几里得可以求出 a g x + b g y = 1 \frac a gx+\frac b gy=1 gax+gby=1 的解,两边再同乘 c g \frac c g gc 就可以得到题目要求的 t t t 了。

要注意负数,要把它变成非负数。


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;

LL gcd (LL a, LL b)
{
	if (!b) return a;
	return gcd (b, a % b);
}
void ex_gcd (LL a, LL b, LL &x, LL &y)
{
	if (!b) {x = 1; y = 0; return;}
	LL X = x, Y = y;
	ex_gcd (b, a % b, X, Y);
	x = Y;
	y = X - (a / b) * Y;
}

int main()
{
	LL p, q, n, m, a, b, c, x, y, g;
	scanf ("%lld%lld%lld%lld%lld", &p, &q, &n, &m, &b);
	a = ((n - m) % b + b) % b;
	c = ((q - p) % b + b) % b;
	g = gcd (a, b);
	if (c % g != 0)
	{
		printf ("Impossible");
		return 0;
	}
	a /= g, b /= g, c /= g;
	ex_gcd (a, b, x, y);
	x = (x % b + b) % b;
	x = x * c % b;
	printf ("%lld", x);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值