PKU2891

题目链接:http://poj.org/problem?id=2891

相关链接:http://blog.csdn.net/lhfight/article/details/7755994

 

package D0718;

/* 
 * 题目大体意思就是求x%ai=ri要求x的最小值
 * 中国剩余定理
 * 对于同余方程组:
 * x=a1 (mod m1)
 * x=a2 (mod m2)
 * 方程组有一个小于m(m1,m2的最小公倍数)的非负整数解的充要条件是(a1-a2)%gcd(m1,m2)=0,同样利用扩展欧几里得算法。两式联立:a1+m1*y=a2+m2*z
 * 则:a1-a2=m2*z-m1*y这样就可以解出z和y,则:x=a2+m2*z
 * 而对于一般情形:(设m1,m2,...mk两两互素)时有:
 * a=b[1] (mod w[1])
 * a=b[2] (mod w[2])
 * .....
 * a=b[n] (mod w[n])
 * 其中w,b已知,w[1],w[2]...w[n]是两两互素的正整数,求a
 * 令W=w[1]*w[2]*...w[n],用W[i]=W/w[i],因为gcd(W[i],w[i])=1,故有;两整数p[i],q[i]满足W[i]*p[i]+w[i]*q[i]=1;如果记e[i]=W[i]*p[i],那么当j!=i时有:e[i]=0 (mod w[j]),当j=i时有:e[i]=1 (mod w[j]);
 * 所以很明显:e[1]*b[1]+e2*b[2]+......e[k]*b[k]就是方程的一个解,加减W倍后就可以得到最小非负整数解了
 * 而对于w[1],w[2].....w[n]不互素的情形,就只能两个两个来求了
 * x=a[1] (mod m[1])
 * x=a[2] (mod m[2])
 * 解完后,a=x,m=m1和m2的最小公倍数
 * 将题目意思转化为公式:a1*x-a2*y=r2-r1,用欧几里得扩展算法求解
 * */
import java.util.Scanner;

public class PKU2891 {
	static boolean flag;
	static long d, x, y;
	static long result;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		long a1, m1, m2, a2, k;
		while (sc.hasNext()) {
			k = sc.nextLong();
			m1 = sc.nextLong();
			a1 = sc.nextLong();
			k -= 1;
			flag = false;
			result = 0;
			x = y = 0;
			d = 0;
			for (int i = 0; i < k; i++) {
				m2 = sc.nextLong();
				a2 = sc.nextLong();
				long b = a2 - a1;
				d = extend_GCD(m1, m2);
				if (b % d != 0)
					flag = true;// 不存在整数解
				result = (x * (b / d) % m2 + m2) % m2;
				a1 = a1 + m1 * result; // 对于求多个方程
				m1 = (m1 * m2) / d; // lcm(m1,m2)最小公倍数;d是m1 和 m2 的最大公约数
				a1 = (a1 % m1 + m1) % m1;
			}
			if (flag)
				System.out.println(-1);
			else
				System.out.println(a1);
		}

	}

	// 扩展的欧几里德
	private static long extend_GCD(long a, long b) {
		long ret, t;
		if (b == 0) {
			x = 1;
			y = 0;
			return a;
		}
		ret = extend_GCD(b, a % b);
		t = x;
		x = y;
		y = t - (a / b) * y;
		return ret;
	}
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怎么演

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值