一个正整数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
中国剩余定理讲解:http://www.cnblogs.com/freinds/p/6388992.html
题意:
解题思路:
(刚开始学习C#,不小心找到了这个题的C#代码就顺便把这个知识点理解理解~)
定理1:几个数相加,如果存在一个加数,不能被数a整除,那么它们的和,就不能被整数a整除。
定理2:两数不能整除,若除数扩大(或缩小)了几倍,而被除数不变,则其商和余数也同时扩大(或缩小)相同的倍数(余数必小于除数)。
现给出求解该问题的具体步骤:
1、求出最小公倍数
lcm=3*5*7=105
2、求各个数所对应的基础数
(1)105÷3=35
35÷3=11……2 //基础数35
(2)105÷5=21
21÷5=4……1
定理2把1扩大3倍得到3,那么被除数也扩大3倍,得到21*3=63//基础数63
3、105÷7=15
15÷7=2……1
定理2把1扩大2倍得到2,那么被除数也扩大2倍,得到15*2=30//基础数30
把得到的基础数加和(注意:基础数不一定就是正数)
35+63+30=128
4、减去最小公倍数lcm(在比最小公倍数大的情况下)
x=128-105=23
那么满足题意得最小的数就是23了。
先给出模板:
#include<stdio.h>
int a[15],m[15];//m[i]是除数,a[i]是余数
void extgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return;
}
extgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-(a/b)*y;
}
int crt(int a[],int m[],int n)
{
int M=1,ans=0,x,y;
for(int i=0;i<n;i++)
M*=m[i];//这几个数相乘
for(int i=0;i<n;i++)//对每个数处理
{
int Mi=M/m[i];
extgcd(Mi,m[i],x,y);//得到符合的解x,y
ans=(ans+Mi*x*a[i])%M;//将每一步的ans累加
}
return (ans+M)%M;//也可写成两句话 if(ans<0) ans+=M; return ans;目的是转化为最小整数
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d",&m[i],&a[i]);
printf("%d",crt(a,m,n));
return 0;
}
AC代码:
#include<stdio.h>
#define ll long long
ll a[15],m[15];//m[i]是除数,a[i]是余数
void extgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return;
}
extgcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-(a/b)*y;
}
int crt(ll a[],ll m[],int n)
{
ll M=1,ans=0,x,y;
for(int i=0;i<n;i++)
M*=m[i];//这几个数相乘
for(int i=0;i<n;i++)//对每个数处理
{
ll Mi=M/m[i];
extgcd(Mi,m[i],x,y);//得到符合的解x,y
ans=(ans+Mi*x*a[i])%M;//将每一步的ans累加
}
return (ans+M)%M;//也可写成两句话 if(ans<0) ans+=M; return ans;目的是转化为最小整数
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lld%lld",&m[i],&a[i]);
printf("%lld\n",crt(a,m,n));
return 0;
}
来个C#代码= =
using System;
using System.IO;
using System.Numerics;
namespace timeless
{
class Program
{
public static long extend_gcd(long a,long b,ref long x,ref long y)
{
if(a==0&&b==0) return -1;
if(b==0)
{
x=1;
y=0;
return a;
}
long d=extend_gcd(b,a%b,ref y,ref x);
y-=a/b*x;
return d;
}
static void Main(string[] args)
{
StreamReader sr=new StreamReader(Console.OpenStandardInput());
StreamWriter sw=new StreamWriter(Console.OpenStandardOutput());
int n=int.Parse(sr.ReadLine());
long M=1;
long[] p=new long[15];
long[] m=new long[15];
string[] str;
for(int i=0;i<n;++i)
{
str=sr.ReadLine().Split(' ');
p[i]=int.Parse(str[0]);
m[i]=int.Parse(str[1]);
M=M*p[i];
}
long pi=0,qi=0;
long res=0;
for(int i=0;i<n;++i)
{
long Mi=M/p[i];
extend_gcd(Mi,p[i],ref pi,ref qi);
res=(res+Mi*pi*m[i])%M;
}
sw.WriteLine((res%M+M)%M);
sw.Flush();
sw.Close();
sw.Close();
}
}
}