[TJOI2009] 猜數字

archer2333發表於2024-10-21

原題連結
\(首先我們來簡單地複習一下中國剩餘定理\)
\(對於x \equiv a_i \mod m_i\)
\(令M= \prod_{i=1}^{n} m_i(其中m_i代表的是除數,a_i代表的是餘數)\)
\(M_i=M/m_i\)
\(t_i \equiv (M_i)^-1 \mod m_i(使用擴充套件歐幾里得算出即可 exgcd)\)
\(因為(t_i*M_i) \equiv 1 \mod m_i 並且 a_i*t_i*M_i \mod m_i==1 (意思為自己對它取模的結果為一) a_i*t_i*M_i \mod M_i==0 (代表其它數對他進行取模結果都為零)\)
\(那麼很明顯符合上式\)
\(所以x=k\prod_{i=1}^{n} m_i+\sum_{i=1}^{n} (t_i*a_i*M_i)\)
\(x \equiv \sum_{i=1}^{n} (t_i*a_i*M-) \mod k\prod_{i=1}^{n} m_i\)
\(經過一系列小學生計算 我們發現這題就是中國剩餘定理的板子題 那麼直接套板子即可透過 因為資料點可能過大 >2e18 所以建議使用__int128__\)
\(code:\)

點選檢視程式碼
plaintext
#include<bits/stdc++.h>

#define int long long
using namespace std;
#define pb push_back
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define i128 __int128
i128 read() {
    __int128 x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

std::ostream &operator<<(std::ostream &os,i128 n){
    std::string s;
    while(n){
        s+='0'+n%10;
        n/=10;
    }
    std::reverse(s.begin(),s.end());
    return os<<s;
}
i128 qpw(i128 a,i128 b,i128 mod){i128 ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
void exgcd(i128 a,i128 b,i128 &x,i128 &y){
    if(b==0){x=1;y=0;return;}
    exgcd(b,a%b,x,y);
    i128 tp=x;
    x=y;y=tp-a/b*y;
}
void print(__int128 x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}

void solve() {
    i128 n;n=read();
    i128 lcm=1,x,y;
    vector<i128>a(n+1),b(n+1);
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i++)b[i]=read(),lcm=lcm*b[i];
    for(int i=1;i<=n;i++)a[i]=(a[i]%b[i]+b[i])%b[i];
    i128 ans=0;
    for(int i=1;i<=n;i++){
        i128 tp=lcm/b[i];
        exgcd(tp,b[i],x,y);
        x=(x%b[i]+b[i])%b[i];
        ans=(ans+x*tp%lcm*a[i]%lcm)%lcm;
    }
    print(ans);
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int _=1;
//    cin>>_;
    while(_--)solve();
}

相關文章