cp-library-cpp

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

View the Project on GitHub suisen-cp/cp-library-cpp

:heavy_check_mark: test/src/polynomial/berlekamp_massey/find_linear_recurrence.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/find_linear_recurrence"

#include <iostream>
#include <atcoder/modint>

#include "library/polynomial/berlekamp_massey.hpp"

using mint = atcoder::modint998244353;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::size_t n;
    std::cin >> n;
    std::vector<mint> s(n);
    for (auto &e : s) {
        int v;
        std::cin >> v, e = v;
    }
    std::vector<mint> C = suisen::find_linear_recuurence(s);
    std::cout << C.size() - 1 << '\n';
    for (std::size_t i = 1; i < C.size(); ++i) {
        std::cout << C[i].val();
        if (i + 1 != C.size()) std::cout << ' ';
    }
    std::cout << '\n';

    return 0;
}
#line 1 "test/src/polynomial/berlekamp_massey/find_linear_recurrence.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/find_linear_recurrence"

#include <iostream>
#include <atcoder/modint>

#line 1 "library/polynomial/berlekamp_massey.hpp"



#include <cassert>
#include <vector>

namespace suisen {
    /**
     * @brief Find linear recurrence in O(|s|^2) time
     * @tparam F Arbitrary field (operator +, -, *, /, +=, -=, *=, /= must be defined)
     * @param s Prefix of a linearly reccurent sequence
     * @return The vector of length L+1 c s.t. c_0=1 and s_i=Sum[j=1,L]c_i*s_{i-j} for all i>=L, where L is the minimum integer s.t. there exists such c of length L+1.
     */
    template <typename F>
    std::vector<F> find_linear_recuurence(const std::vector<F>& s) {
        std::vector<F> B{ 1 }, C{ 1 };
        B.reserve(s.size()), C.reserve(s.size());
        F b = 1;
        std::size_t L = 0;
        for (std::size_t N = 0, x = 1; N < s.size(); ++N) {
            F d = s[N];
            for (std::size_t i = 1; i <= L; ++i) d += C[i] * s[N - i];
            if (d == 0) {
                ++x;
            } else {
                F c = d / b;
                if (C.size() < B.size() + x) C.resize(B.size() + x);
                if (2 * L > N) {
                    for (std::size_t i = 0; i < B.size(); ++i) C[x + i] -= c * B[i];
                    ++x;
                } else {
                    std::vector<F> T = C;
                    for (std::size_t i = 0; i < B.size(); ++i) C[x + i] -= c * B[i];
                    L = N + 1 - L, B = std::move(T), b = d, x = 1;
                }
            }
        }
        C.resize(L + 1);
        for (std::size_t N = 1; N <= L; ++N) C[N] = -C[N];
        return C;
    }
} // namespace suisen



#line 7 "test/src/polynomial/berlekamp_massey/find_linear_recurrence.test.cpp"

using mint = atcoder::modint998244353;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::size_t n;
    std::cin >> n;
    std::vector<mint> s(n);
    for (auto &e : s) {
        int v;
        std::cin >> v, e = v;
    }
    std::vector<mint> C = suisen::find_linear_recuurence(s);
    std::cout << C.size() - 1 << '\n';
    for (std::size_t i = 1; i < C.size(); ++i) {
        std::cout << C[i].val();
        if (i + 1 != C.size()) std::cout << ' ';
    }
    std::cout << '\n';

    return 0;
}
Back to top page