Fu_L's Library

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

View the Project on GitHub Fu-L/cp-library

:heavy_check_mark: berlekamp_massey
(src/fps/berlekamp_massey.hpp)

berlekamp_massey

FPS<mint> berlekamp_massey(FPS<mint> s)

斉次線形漸化式

\[a_i = \sum\limits_{j = 0}^{d - 1} c_j a_{i - 1 - j}\]

の形で表される線形回帰数列 $a$ の前 $N$ 項が与えられたときに,数列 $c$ を返します.

$c$ を一意に確定させるためには $N \geq 2d$ が必要です.
$c$ が一意に定まらない場合,条件を満たす $c$ のうち,最も $d$ を小さいものを返します.

計算量

Depends on

Required by

Verified with

Code

#pragma once
#include "../template/template.hpp"
template <template <typename> typename FPS, typename mint>
FPS<mint> berlekamp_massey(const FPS<mint>& s) {
    const int n = (int)s.size();
    FPS<mint> b = {mint(-1)}, c = {mint(-1)};
    mint y = mint(1);
    for(int ed = 1; ed <= n; ++ed) {
        int l = (int)c.size(), m = (int)b.size();
        mint x = 0;
        for(int i = 0; i < l; ++i) x += c[i] * s[ed - l + i];
        b.emplace_back(0);
        ++m;
        if(x == mint(0)) continue;
        const mint freq = x / y;
        if(l < m) {
            const auto tmp = c;
            c.insert(begin(c), m - l, mint(0));
            for(int i = 0; i < m; ++i) c[m - 1 - i] -= freq * b[m - 1 - i];
            b = tmp;
            y = x;
        } else {
            for(int i = 0; i < m; ++i) c[l - 1 - i] -= freq * b[m - 1 - i];
        }
    }
    c.pop_back();
    c = c.rev();
    return c;
}
#line 2 "src/template/template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<long long, long long>;
#define rep(i, a, b) for(long long i = (a); i < (b); ++i)
#define rrep(i, a, b) for(long long i = (a); i >= (b); --i)
constexpr long long inf = 4e18;
struct SetupIO {
    SetupIO() {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout << fixed << setprecision(30);
    }
} setup_io;
#line 3 "src/fps/berlekamp_massey.hpp"
template <template <typename> typename FPS, typename mint>
FPS<mint> berlekamp_massey(const FPS<mint>& s) {
    const int n = (int)s.size();
    FPS<mint> b = {mint(-1)}, c = {mint(-1)};
    mint y = mint(1);
    for(int ed = 1; ed <= n; ++ed) {
        int l = (int)c.size(), m = (int)b.size();
        mint x = 0;
        for(int i = 0; i < l; ++i) x += c[i] * s[ed - l + i];
        b.emplace_back(0);
        ++m;
        if(x == mint(0)) continue;
        const mint freq = x / y;
        if(l < m) {
            const auto tmp = c;
            c.insert(begin(c), m - l, mint(0));
            for(int i = 0; i < m; ++i) c[m - 1 - i] -= freq * b[m - 1 - i];
            b = tmp;
            y = x;
        } else {
            for(int i = 0; i < m; ++i) c[l - 1 - i] -= freq * b[m - 1 - i];
        }
    }
    c.pop_back();
    c = c.rev();
    return c;
}
Back to top page