孙子定理 互质与非互质
2019-04-14 17:44 发布
生成海报
互质
输入 :
x = ai (mod ni) (i=1,2...,k)
令:
n=n1*n2*.....*nk;
mi=n/ni;
ci=mi(mi^ -1 mod ni)
ans=(a1*c1+a2*c2+......+ak*ck)(mod n)
非互质
结论:
x = a1 (mod n1)
x = a 2 (mod n 2)
-->
x= a ( mod n)
其中a=a1+n1*K;(K为n1k1=a2-a1(mod n2)最小非负解)
n=lcm(n1,n2);
证明:
Res = a1+n1*k1 ①
Res = a2+n2*k2
即 a1+n1*k1 = a2+n2*k2
令d = gcd (n1, n2)
左右2边同时除以d并整理得
n1*k1/d – (a2-a1)/d = n2*k2/d = (n2/d)*k2
∴有 n1*k1/d – (a2-a1)/d = 0 (mod n2/d) n1*k1 = (a2-a1) (mod n2/d)
易知k1有多个解
设K`为k1的解,必然存在最小非负整数K` 使得得 k1 = K` (mod n2/d) ③
即k1 = K` + (n2/d)*C ② (设C为某一整数)
②代入①得
Res = a1 + n1*( K` + (n2/d)*C) Res = a1 + n1*K` + (n1*n2/d)*C
即Res – (a1+n1*K`) = 0 (mod (n1*n2/d))
Res = (a1+n1*K`) (mod (n1*n2/d))
//poj1006
#include
#include
typedef int ll;
using namespace std;
const int n[]={0,23,28,33};
const int m[]={0,924,759,644};
int m1[4];
int c[4];
const int nn=21252;
struct sol{
ll x,y,d;
sol(ll xx=0,ll yy=0,ll dd=0){
x=xx; y=yy; d=dd;
}
};
inline sol gcd(ll a,ll b)
{
if (b==0) return sol(1,0,a);
sol temp=gcd(b,a%b);
ll x1=temp.x,y1=temp.y,d1=temp.d;
return sol(y1,x1-a/b*y1,d1);
}
int p,e,k,start,cas=0;
int ans;
int main()
{
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
for (int i=1;i<=3;i++)
m1[i]=gcd(m[i],n[i]).x;
for (int i=1;i<=3;i++)
c[i]=m[i]*((m1[i]%n[i]+n[i])%n[i]);
while (scanf("%d%d%d%d",&p,&e,&k,&start))
{
if (p==-1 && e==-1 && k==-1 && start==-1) break;
ans=(p*c[1]+e*c[2]+k*c[3]-start)%nn;
ans=(ans%nn+nn-1)%nn+1;
printf("Case %d: the next triple peak occurs in %d days.
",++cas,ans);
}
return 0;
}
//poj2891
#include
#include
#include
#define cl(x) memset(x,0,sizeof(x))
typedef __int64 ll;
inline ll gcd(ll a,ll b,ll& x,ll& y)
{
if (b==0)
{
x=1; y=0; return a;
}
ll temp,d=gcd(b,a%b,x,y);
temp=x;
x=y; y=temp-a/b*y;
return d;
}
inline ll solve(ll a,ll b,ll n)
{
ll sol,x,y;
ll d=gcd(a,n,x,y);
if (b%d==0)
{
sol=x*b/d;
ll r=n/d;
sol=(sol%r+r)%r;
return sol;
}
else
return -1;
}
inline bool merge(ll a1,ll n1,ll a2,ll n2,ll &a,ll &n)
{
ll x,y,c=a2-a1;
ll d=gcd(n1,n2,x,y);
ll K=solve(n1,c,n2);
if (K==-1)
return false;
a=a1+n1*K;
n=n1*n2/d;
return true;
}
ll A,N;
ll newa,newn;
ll ans;
int main()
{
int k;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
while (~scanf("%d",&k))
{
int flag=0;
scanf("%I64d%I64d",&N,&A);
for (register int i=1;i
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮