首页 > 代码库 > HDU 1788 Chinese remainder theorem again 中国剩余定理

HDU 1788 Chinese remainder theorem again 中国剩余定理

题意:

给定n,AA

下面n个数m1,m2···mn

则有n条方程

res % m1 = m1-AA

res % m2 = m2-AA

问res的最小值

直接上剩余定理,嘿嘿

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<queue>
#include<vector>
using namespace std;
#define ll __int64
ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a%b);
}
//求一组解(x,y)使得 ax+by = gcd(a,b), 且|x|+|y|最小(注意求出的 x,y 可能为0或负数)。
//下面代码中d = gcd(a,b)
//可以扩展成求等式 ax+by = c,但c必须是d的倍数才有解,即 (c%gcd(a,b))==0
void extend_gcd (ll a , ll b , ll& d, ll &x , ll &y) {  
	if(!b){d = a; x = 1; y = 0;}
	else {extend_gcd(b, a%b, d, y, x); y-=x*(a/b);}
}
ll work(ll l, ll r, ll *m, ll *a){
	ll lcm = 1;
	for(ll i = l; i <= r; i++)lcm = lcm/gcd(lcm,m[i])*m[i];
	for(ll i = l+1; i <= r; i++) {
		ll A = m[l], B = m[i], d, k1, k2, c = a[i]-a[l];
		extend_gcd(A,B,d,k1,k2);
		if(c%d)return -1;
		ll mod = m[i]/d;
		ll K = ((k1*c/d)%mod+mod)%mod;
		a[l] = m[l]*K + a[l];
		m[l] = m[l]*m[i]/d;
	}
	if(a[l]==0)return lcm;
	return a[l];
}
#define N 100
ll a[N], m[N], n, AA;;
int main(){
	ll i;
	while(cin>>n>>AA,n){
		for(i=1;i<=n;i++)cin>>m[i];
		for(i=1;i<=n;i++)a[i] = m[i]-AA;
		cout<<work(1,n,m,a)<<endl;
	}
	return 0;
}