中国余数定理 先学扩展欧几里得吧>,<
看这篇
http://www.cnblogs.com/walker01/archive/2010/01/23/1654880.html
模数互质的情况FZU 1402
//模数互质的情况
#include<stdio.h>
#include<math.h>
#define ll __int64
ll div[15],rem[15];
ll n,d,x,y;
void ext_gcd(ll a,ll b) //求出a*x+b*y=gcd(a,b)=1时的X
{
if(b==0)
{
x=1,y=0,d=a;
return ;
}
else
{
ext_gcd(b,a%b);
ll tmp=x;
x=y;
y=tmp-a/b*y;
}
}
ll china_remainder(ll a[],ll b[])
{
ll lcm=1;
ll ans=0;
int i;
for(i=0;i<n;i++)
lcm*=a[i];
for(i=0;i<n;i++)
{
ll m=lcm/a[i];
ext_gcd(m,a[i]);
x=(x%a[i]+a[i])%a[i];//模数互质的情况下 此时求出的X就是a*x=1(mod b)
ans=(ans+m*x*b[i]%lcm)%lcm;
}
return ans;
}
int main()
{
freopen("in.txt","r",stdin);
while(scanf("%d",&n)==1)
{
int i,j;
for(i=0;i<n;i++)
scanf("%I64d%I64d",&div[i],&rem[i]);
printf("%I64d\n",china_remainder(div,rem));
}
return 0;
}
模数不互质的情况 HDU3579
这篇原理讲得比较清楚 http://972169909-qq-com.iteye.com/blog/1266328
//模数不互质的情况,合并同余方程
#include<stdio.h>
#include<math.h>
#define ll __int64
ll div[10],rem[10];
ll n,d,x,y;
ll gcd(ll a,ll b)
{ return b==0?a:gcd(b,a%b);}
void ext_gcd(ll a,ll b)
{
if(b==0)
{
x=1,y=0,d=a;
return ;
}
else
{
ext_gcd(b,a%b);
ll tmp=x;
x=y;
y=tmp-a/b*y;
}
}
ll china_remainder2(ll a[],ll b[])
{
int flag=0;
ll n1=a[0],b1=b[0],n2,b2,c;
for(int i=1;i<n;i++)//依据上面所推公式进行合并
{
n2=a[i],b2=b[i];
c=b2-b1;
ext_gcd(n1,n2);
if(c%d)
{
flag=1;
break;
}
ll k=c/d*x;
ll t=n2/d;
if(t<0) t=-t;
k=(k%t+t)%t;
b1=b1+n1*k;
n1=n1/d*n2;
}
if(flag)
return -1;
if(b1==0)//这题余数可能为0,需要特判,如果都为0,B1为所以除数的最小公倍数
b1=n1;
return b1;
}
int main()
{
freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
int ii;
for(ii=1;ii<=t;ii++)
{
int i;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%I64d",&div[i]);
for(i=0;i<n;i++)
scanf("%I64d",&rem[i]);
printf("Case %d: %I64d\n",ii,china_remainder2(div,rem));
}
return 0;
}