孙子定理
链接:https://www.nowcoder.com/acm/contest/75/B
来源:牛客网
题目描述
uu遇到了一个小问题,可是他不想答。你能替他解决这个问题吗?
问题:给你k对a和r是否存在一个正整数x使每队a和r都满足:x mod a=r,求最小正解x或无解。
问题:给你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
输出
31
#include<bits/stdc++.h>
using namespace std;
long long a[100006],m[100006];
void ex(long long b,long long c,long long &d,long long int &x,long long int &y)
{
if(!c){
d=b; x=1; y=0;
}
else{
ex(c,b%c,d,y,x);
y-=x*(b/c);
}
}
long long china(int n)
{
long long m1,r1;
m1=a[0],r1=m[0];
for(int i=1;i<n;i++){
long long m2=a[i],r2=m[i];
long long int x,y,d,e;
ex(m1,m2,d,x,y);
e=r2-r1;
if(e%d){
return -1;
}
long long t=m2/d;
x=(e/d*x%t+t)%t;
r1=m1*x+r1;
m1=m1*m2/d;
}
if(n==1&&r1==0) return m1;
return r1;
}
int main()
{
long long n;
while( ~scanf("%lld",&n)){
for(int i=0;i<n;i++)
scanf("%lld%lld",&a[i],&m[i]);
long long out;
out = china(n);
printf("%lld\n",out);
memset( a, 0, sizeof(a));
memset( m, 0, sizeof(m));
}
return 0;
}
运用扩展欧几里得算法求出乘法逆元,逆元乘上除数相加。

浙公网安备 33010602011771号