AtCoder ABC 319E 中国剩余定理

题意

传送门 AtCoder ABC 319E Bus Stops

题解

对于停车点间的每一段距离,仅跟抵达前驱车站模 P i P_i Pi 的模数相关。考虑中国剩余定理 x m o d    n ↔ ( x m o d    a , x m o d    b ) , n = a ⋅ b , g c d ( a , b ) = 1 x\mod n \leftrightarrow (x\mod a, x\mod b),n=a\cdot b,gcd(a,b)=1 xmodn(xmoda,xmodb),n=ab,gcd(a,b)=1。题目中的 P i P_i Pi 虽然不一定互素,但转化的思想基本一致,即:令 M = l c m ( 1 , 2 , ⋯   , 8 ) M=lcm(1,2,\cdots,8) M=lcm(1,2,,8) x m o d    M → ( x m o d    1 , ⋯   , x m o d    8 ) x\mod M\rightarrow (x\mod 1, \cdots, x\mod 8) xmodM(xmod1,,xmod8),同时考虑线性同余方程组的求解,相反方向的推论也成立。那么预处理出 0 , 1 , ⋯ M 0,1,\cdots M 0,1,M 的答案,再加上 ⌊ q / M ⌋ ⋅ M \lfloor q/M\rfloor \cdot M q/MM 即可。总时间复杂度 O ( M N + Q ) O(MN+Q) O(MN+Q)

#include 
using namespace std;
constexpr int MOD = 840;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, x, y;
    cin >> n >> x >> y;
    n -= 1;
    vector<int> p(n), t(n);
    for (int i = 0; i < n; ++i) {
        cin >> p[i] >> t[i];
    }
    using ll = long long;
    auto get = [&](int bg) {
        ll v = bg + x;
        for (int i = 0; i < n; ++i) {
            int m = v % p[i];
            if(m > 0) {
                v += p[i] - m;
            }
            v += t[i];
        }
        v += y;
        return v;
    };
    vector<ll> mem(MOD);
    for (int i = 0; i < MOD; ++i) {
        mem[i] = get(i);
    }
    int q;
    cin >> q;
    while (q--) {
        int k;
        cin >> k;
        ll res = k / MOD * MOD + mem[k % MOD];
        cout << res << '\n';
    }

    return 0;
}

你可能感兴趣的:(数学,算法)