1. 程式人生 > >P3868 [TJOI2009]猜數字

P3868 [TJOI2009]猜數字

printf max [1] tps else return 代碼 uid mat

中國剩余定理的模板題。

雖然說是CRT的模板,但是我不會CRT啊。我只會EXCRT

思路很清晰,都寫在註釋裏面了。不懂的話看看我前面寫過的一篇模板題的隨筆。

PS:很榮幸能夠幫到@niiick大佬。我幫大佬指正了一個小學生才糾結的東西。。。

技術分享圖片

代碼:

#include<cstdio>
#include<cmath>

const int maxn = 15;
#define ll long long
ll a[maxn], b[maxn], n;

ll exgcd(ll a, ll b, ll &x, ll &y)
{
    if(b == 0){ x = 1; y = 0; return a; }
    else
    {
        ll ret = exgcd(b, a % b, x, y);
        ll t = x;
        x = y;
        y = t - a / b * y;
        return ret;
    }
}
ll excrt()
{
    ll ans = a[1], M = b[1];
    for(int i = 2; i <= n; i++)
    {
        // ans + k * M
        // ans + t * M === a[i] (mod b[i])
        // t * M === a[i] - ans (mod b[i])
        // t * M - yy * b[i] = a[i] - ans
        // solve it through x * M - y * b[i] = gcd(M, b[i])
        // t : x = a[i] - ans : gcd(M, b[i])
        // t - bg = t - b[i] / gcd(M, b[i])
        // upd
        
        ll A = M, B = b[i], C = ((a[i] - ans) % b[i] + b[i]) % b[i];
        ll x, y;
        ll g = exgcd(A, B, x, y);
        if(C % g != 0) return -1;
        ll bg = B / g;
        x = x * C / g % b[i];
        x = (x + bg) % bg + bg;
        ans += x * M;
        M *= bg;
        ans = (ans % M + M) % M;
    }
    return (ans % M + M) % M;
}
int main()
{
    // b_i | (n - a_i)
    // n - a_i % b_i = 0
    // n - a_i === 0 (mod b_i)
    // n === a_i (mod b_i)
    scanf("%lld", &n);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    for(int i = 1; i <= n; i++) scanf("%lld", &b[i]);
    printf("%lld\n", excrt());
    return 0;
}

P3868 [TJOI2009]猜數字