barley zhenzhendong
Weeks prior guidance over the side of the blog but abandoned treatment, and today they celebrate again.
Problem Description
Given a length \ (n-\) is the number of columns \ (\ {a_i \} \) , seeking a shortest linear recursion Sequence \ (\ {B_i \} \) (set length \ (m \) ), such that for all \ (m \ Leq K \ n-Leq \) , there are \ (a_k = \ sum_ {i = 0} ^ m a_ {k - i} b_i \)
Complexity Requirements: \ (O (^ n-2) \)
A look very fit with constant coefficients of linear recursion consumption.
Algorithmic process
Incremental Construction.
Suppose we have calculated the current \ (A_ {0 ... I -. 1} \) . The linear recurrence Sequence calculation process, we have obtained had \ (C \) a recursion formula, the \ (I \) a recursive formula in \ (fail_i \) position for the first time ineffective.
Beginning \ (c = 0 \) , we have an empty recursive.
Now we add the number \ (a_i \) .
Set \ (R_c \) length of \ (m \) , \ (= a_i delta_i - \ sum_ K = {}. 1 A_ ^ {m} I {-} R_c K (K) \)
If \ (delta_i = 0 \) , \ (R_c \) is still a legitimate recursive.
Otherwise, we want to \ (R_c \) to make adjustments to get a new recursive qualified.
If \ (C = 0 \) , then the first \ (i - 1 \) number is \ (0 \) we only need to construct comprising a. \ (I \) a \ (0 \) recursive formula i.e. can.
If \ (C \ 0 = Not \) , only need to construct a recursive \ (R & lt '\) , when the \ (| R' | + 1 \ leq k <n \) when, \ (\ I = {sum_ ^ {}. 1 | R & lt '| {K} A_ - R'_i I} = 0 \) , \ (\ sum_. 1} ^ {I = {| R & lt' |} n-A_ {-} I = delta_n R'_i \) , then the \ (R_ {c + 1} = R_c + R '\) becomes eligible.
We just look for a $ 0 \ leq id <c $ , its front \ (fail_ {id} - 1 \) number is \ (0 \) on it if we make a displacement, i.e., the front fill. \ ( i - fail_ {id} - 1 \) a \ (0 \) , followed by a \ (1 \) , and then connect \ (- R_ {ID} \) , we can get only a location \ (I \ ) is \ (delta_time_unit_address ID} {} {fail_ \) , the remaining positions are \ (0 \) of the array. then we multiply it entire \ (tmp = \ frac {delta_ {i}} {delta_ {fail_ { }}} ID \) , to construct a \ (R '\)
I.e. \ (R '\) to
\ [\ {0,0, ... 0 , tmp, -tmp R_ {id} (1), - tmp R_ {id} (2), ... \} \ ]
Then we have to ensure \ (R_c + R '\) is the shortest, we find \ (i - fail_ the above mentioned id} {+ | R_ {the above mentioned id} | \) . The minimum you can (not strict proof)
template
Data can go weeks guidance blog point of view.
#pragma GCC optimize("2,Ofast,inline")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define LL long long
#define pii pair<int, int>
using namespace std;
const int mod = 1e9 + 7;
template <typename T> T read(T &x) {
int f = 0;
register char c = getchar();
while (c > '9' || c < '0') f |= (c == '-'), c = getchar();
for (x = 0; c >= '0' && c <= '9'; c = getchar())
x = (x << 3) + (x << 1) + (c ^ 48);
if (f) x = -x;
return x;
}
inline void upd(int &x, int y) {
(x += y) >= mod ? x -= mod : 0;
}
inline int add(int x, int y) {
return (x += y) >= mod ? x - mod : x;
}
inline int dec(int x, int y) {
return (x -= y) < 0 ? x + mod : x;
}
inline int Qpow(int x, int p) {
int ans = 1;
for (; p; p >>= 1) {
if (p & 1) ans = 1LL * ans * x % mod;
x = 1LL * x * x % mod;
}
return ans;
}
inline int Inv(int x) {
return Qpow(x, mod - 2);
}
namespace BM {
const int Maxn = 5005;
int n, c;
int a[Maxn], del[Maxn], fail[Maxn];
vector<int> R[Maxn];
vector<int> solve() {
c = 0;
for (int i = 1; i <= n; ++i) {
if (c == 0) {
if (a[i]) {
fail[0] = i;
++c;
del[i] = a[i];
fail[c] = i;
R[c].resize(i);
}
continue;
}
del[i] = a[i];
for (int j = 0; j < R[c].size(); ++j) {
del[i] = dec(del[i], 1LL * R[c][j] * a[i - j - 1] % mod);
}
if (del[i] == 0) continue;
fail[c] = i;
int id = c - 1, v = i - fail[id] + R[id].size();
for (int j = c - 1; j >= 0; --j) {
if (v > i - fail[j] + R[j].size()) {
v = i - fail[j] + R[j].size();
id = j;
}
}
int p = i - fail[id];
int tmp = 1LL * del[i] * Inv(del[fail[id]]) % mod;
R[c + 1] = R[c];
if (R[c + 1].size() < v) R[c + 1].resize(v);
upd(R[c + 1][p - 1], tmp);
for (int j = 0; j < R[id].size(); ++j) {
upd(R[c + 1][p + j], -1LL * tmp * R[id][j] % mod + mod);
}
++c;
}
if (c == 0) return vector<int>(0);
return R[c];
}
}
using namespace BM;
int main() {
read(n);
for (int i = 1; i <= n; ++i) read(a[i]);
vector<int> ans = BM::solve();
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); ++i)
cout << ans[i] << ' ';
puts("");
}