library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub Series-205/library

:warning: convolution/bostan_mori.cpp

Code

// [x^N] P(x)/Q(x)
// O(K log K log N) (convolution)
// O(K^2 log N) (simple)
// Q[0] = 1, deg(P) < deg(Q) = K
mint bostan_mori(vector<mint> P, const vector<mint>& Q, ll N) {
    // cout << P[0].val() << " " << Q[0].val() << endl;
    if(N == 0) {
        return P[0] / Q[0];
    }

    int K = (int)Q.size();
    P.resize(K - 1);

    vector<mint> minusQ = Q;
    for(int i = 1; i < K; i += 2) {
        minusQ[i] *= -1;
    }

    auto PQ = atcoder::convolution(P, minusQ);
    auto QQ = atcoder::convolution(Q, minusQ);
    // auto PQ = mul(P, minusQ);
    // auto QQ = mul(Q, minusQ);

    vector<mint> nextP(K - 1), nextQ(K);
    for(int i = 0; i < K - 1; i++) {
        nextP[i] = PQ.at(i * 2 + N % 2);
    }
    for(int i = 0; i < K; i++) {
        nextQ[i] = QQ.at(i * 2);
    }

    return bostan_mori(nextP, nextQ, N / 2);
}
#line 1 "convolution/bostan_mori.cpp"


// [x^N] P(x)/Q(x)
// O(K log K log N) (convolution)
// O(K^2 log N) (simple)
// Q[0] = 1, deg(P) < deg(Q) = K
mint bostan_mori(vector<mint> P, const vector<mint>& Q, ll N) {
    // cout << P[0].val() << " " << Q[0].val() << endl;
    if(N == 0) {
        return P[0] / Q[0];
    }

    int K = (int)Q.size();
    P.resize(K - 1);

    vector<mint> minusQ = Q;
    for(int i = 1; i < K; i += 2) {
        minusQ[i] *= -1;
    }

    auto PQ = atcoder::convolution(P, minusQ);
    auto QQ = atcoder::convolution(Q, minusQ);
    // auto PQ = mul(P, minusQ);
    // auto QQ = mul(Q, minusQ);

    vector<mint> nextP(K - 1), nextQ(K);
    for(int i = 0; i < K - 1; i++) {
        nextP[i] = PQ.at(i * 2 + N % 2);
    }
    for(int i = 0; i < K; i++) {
        nextQ[i] = QQ.at(i * 2);
    }

    return bostan_mori(nextP, nextQ, N / 2);
}
Back to top page