[牛客網]15068一個小問題(擴展中國剩餘定理)

傳送門:https://ac.nowcoder.com/acm/problem/15068

題目描述:

uu遇到了一個小問題,可是他不想答。你能替他解決這個問題嗎?
問題:給你k對a和r是否存在一個正整數x使每隊a和r都滿足:x mod a=r,求最小正解x或無解。

輸入描述:

第一行是正整數k(k<=100000)
接下來k行,每行有倆個正整數a,r(100000>a>r>=0)

輸出描述:

在每個測試用例輸出非負整數m,佔一行。
如果有多個可能的值,輸出最小的值。
如果沒有可能的值,則輸出-1。

示例1輸入:

2
8 7
11 9

示例1輸出:

31

分析:

顯然,是一道擴展中國剩餘定理的模板題。

代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=1e6+10;
ll K,C[MAXN],M[MAXN],x,y;
ll gcd(ll a,ll b) {
    return b==0?a:gcd(b,a%b);
}
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	ll d=exgcd(b,a%b,x,y),tmp;
	tmp=x;
	x=y;
	y=tmp-(a/b)*y;
	return d;
}
ll inv(ll a, ll b) {
    ll r=exgcd(a,b,x,y);
    while (x<0) x+=b;
    return x;
}
int main(){
	int flag=1;
	scanf("%lld",&K);
	for(ll i=1;i<=K;i++)
		scanf("%lld%lld",&M[i],&C[i]);
	for(ll i=2;i<=K;i++) {
        ll M1=M[i-1],M2=M[i],C2=C[i],C1=C[i-1],T=gcd(M1,M2);
        if((C2-C1)%T!=0){
			flag=0;
			break;
		}
        M[i]=(M1*M2)/T;
        C[i]=(inv(M1/T,M2/T)*(C2-C1)/T)%(M2/T)*M1+C1;
        C[i]=(C[i]%M[i]+M[i])%M[i];
    }
    printf("%lld\n",flag?C[K]:-1);
	return 0;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章