现在的位置: 首页 > 综合 > 正文

POJ 2891 Strange Way to Express Integers

2019年04月09日 ⁄ 综合 ⁄ 共 910字 ⁄ 字号 评论关闭

大意不再赘述。

思路:

线性同余方程的应用。

令m = lcm(m1, m2);
x ≡ b1 (mod m1)
x ≡ b2 (mod m2)
以上等价于 x = b1 + m1y1; x = b2 + m2y2;
联立可得:
b1 + m1y1 = b2 + m2y2,即m1y1 - m2y2 = b2-b1;
易知此方程的解为y2,因此小于m的非负整数解即为(b2 + m2y2) % m
迭代的时候注意,余数要变为b1 = m1*x0 + b1; m1 = (m1*m2);
为什么可以这样?
x ≡ b1 (mod m1)
x ≡ b2 (mod m2)
令m = lcm(m1, m2);
设m = z1 * m1 = z2 * m2;
x = b1 + m1*y1; (1)
x = b2 + m2*y2; (2)
x' = m*y3 + x;  (3)
把(1)带入(3),得 x' = b1 + m1*y1 + z1*m1*y3 = b1 + (y1+z1*y3)*b1,符合要求。
所以两个式子合并后的结果就是:
x' ≡ x (mod m),其中m = lcm(m1, m2);

一直迭代下去,就可以得到结果。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;

typedef long long LL;

LL n;

void ex_gcd(LL a, LL b, LL &d, LL &x, LL &y)
{
	if(!b)
	{
		d = a; x = 1; y = 0;
	}
	else
	{
		ex_gcd(b, a%b, d, y, x);
		y -= x*(a/b);
	}
}

LL solve()
{
	LL a, b, d, x, y;
	LL a1, r1, a2, r2;
	scanf("%lld%lld", &a1, &r1);
	int f = 0;
	for(int i = 1; i < n; i++)
	{
		scanf("%lld%lld", &a2, &r2);
		a = a1, b = a2;
		ex_gcd(a, b, d, x, y);
		if((r2-r1) % d) f = 1;
		int b1 = b / d;
		x *= (r2-r1) / d;
		x = (x%b1+b1) % b1;
		r1 = a1*x + r1;
		a1 = a1*(a2/d);
	}
	return f ? -1 : r1;
}

int main()
{
	while(~scanf("%lld", &n))
	{
		printf("%lld\n", solve());
	}
	return 0;
}

抱歉!评论已关闭.