题目:
一个正整数K,给出K Mod 一些质数的结果,求符合条件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合条件的最小的K = 23。
Input
第1行:1个数N表示后面输入的质数及模的数量。(2 <= N <= 10)
第2 - N + 1行,每行2个数P和M,中间用空格分隔,P是质数,M是K % P的结果。(2 <= P <= 100, 0 <= K < P)
Output
输出符合条件的最小的K。数据中所有K均小于10^9。
Sample Input
3
2 1
3 2
5 3
Sample Output
23
代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
ll m[15],a[15],res,M;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b){
x = 1;
y = 0;
return a;
}
res = exgcd(b,a % b,x,y);
int temp = x;
x = y;
y = temp - a / b * y;
return res;
}
ll CRT(ll m[],ll a[],ll n)
{
ll x,y,b[15];
ll ans = 0;
M = 1;
for(int i = 0;i < n;i++) M *= m[i];
for(int i = 0;i < n;i++) b[i] = M / m[i];
for(int i = 0;i < n;i++){
exgcd(b[i],m[i],x,y);
ans += a[i] * x * b[i];
}
return ans;
}
int main()
{
ll n,sum;
cin >> n;
for(int i = 0;i < n;i++) cin >> m[i] >> a[i];
sum = CRT(m,a,n);
sum %= M;
while(sum <= 0) sum += M;
cout << sum << endl;
return 0;
}
题意:
中文题,不解释了。
思路:
这道题用到中国式剩余定理,直接套用模板就可以了。这里要求求最小的正整数,所以求出一个解之后还要取模。
下面来证明一下中国式剩余定理:
在此之前你需要知道公式:a % b = (a + kb) % b = c
a % b = c
(ak) % b = kc
先举个例子,有下列一组方程:
x ≡ 2(mod3)
x ≡ 3(mod5)
x ≡ 2(mod7)
要你求出满足这三个方程的x,且x是最小正整数,假设x =2 * n1 + 3 * n2 + 2 * n3(这里就用到上述公式)
那么对于第一个方程x ≡ 2(mod3),假设其解为n1。
那么n1就满足:
n1 ≡ 1(mod3)
n1 ≡ 0(mod5)
n1 ≡ 0(mod7) 这三个式子,因为n1在满足第一个式子的时候,不能对之后两个式子造成影响,必须要保证mod另外两个数也要为0。
那么可以得出n1 = 5 * 7 * c = 35 * c
因为n1满足第一个式子,所以35c ≡ 1(mod3)
又因为 35≡ -1(mod3)
两式相除 c ≡ -1(mod3) ==> c = 2
n1 = 70
同理n2 要满足如下:
n2 ≡ 0(mod3)
n2 ≡ 1(mod5)
n2 ≡ 0(mod7)
求得n2 = 21
n3 = 15
那么x = 2 * 70 + 3 * 21 + 2 * 15 = 233
此时x还不满足最小正整数,所以要对3 * 5 * 7取模(这三个方程mod的那些数的最小公倍数)
==> x = 23
现在如果对于一般情况:
x ≡ a1(mod m1)
x ≡ a2(mod m2)
x ≡ a3(mod m3)
…
x ≡ an(mod mn)
这里M = m1 * m2 * . …* mn
M[i] = M / mi
t[i]为M[i]的逆元
x = (M[1] * a1 * t[1] + M[2] * a2 * t[2] + … + M[n] * an * t[n]) % M
这道题就直接套用这个公式就可以求出了,t[i]要用到扩展欧几里得算法。