1. 程式人生 > >CRT【p3868】[TJOI2009]猜數字

CRT【p3868】[TJOI2009]猜數字

Description

現有兩組數字,每組k個,第一組中的數字分別為:a1,a2,...,ak表示,第二組中的數字分別用b1,b2,...,bk表示。其中第二組中的數字是兩兩互素的。求最小的非負整數n,滿足對於任意的i,n - ai能被bi整除。

Input

輸入資料的第一行是一個整數k,(1 ≤ k ≤ 10)。接下來有兩行,第一行是:a1,a2,...,ak,第二行是b1,b2,...,bk

Output

輸出所求的整數n。

\(CRT\)

通過讀題,我們可以得到一群這樣的關係
\[ n-a_i \equiv 0(mod \ b_i) \]
然後移項
\[ n \equiv a_i(mod \ b_i) \]


\(What's \ this?\)中國剩餘定理。

懶得在這推了,所以就是裸的\(CRT\)問題了。

放下程式碼好了。

程式碼

#include<cstdio>
#include<iostream>
#include<algorithm>
#define int long long 
#define R register

using namespace std;

const int gz=18;

inline void in(R int &x)
{
    R int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}

int a[gz],b[gz],N=1,n,ans;

int exgcd(R int a,R int b,R int &x,R int &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    R int t=exgcd(b,a%b,x,y);
    R int tmp=x;
    x=y;y=tmp-a/b*y;
    return t;
}

inline int mul(R int x,R int y)
{
    R int res=0;
    for(;y;y>>=1,x=(x+x)%N)
        if(y&1)res=(res+x)%N;
    return res;
}

inline void China()
{
    for(R int i=1;i<=n;i++)
    {
        R int bb=N/b[i];
        R int aa=b[i];
        R int x,y;
        exgcd(aa,bb,x,y);
        (y+=b[i])%=b[i];
        R int tmp=mul(bb,y)%N;
        (ans+=mul(a[i],tmp)%N)%=N;
    }
}

signed main()
{
    in(n);
    for(R int i=1;i<=n;i++)in(a[i]);
    for(R int i=1;i<=n;i++)in(b[i]),N*=b[i];
    China();
    printf("%lld",(ans+N)%N);
}