宣告:博主已退役,這是以前的總結,如有錯誤望指正,如有問題不妨看看別人的部落格給乙個序列\(\\)
要求最短的序列\(\\)
使得對於所有\(i>m\)有
\[a_i=\sum_^f_k*a_
\]主要思想是依次考慮每個\(a_i\)
不斷修改\(\\)
使得其在保證正確的同時盡量短
一開始\(\\)為空
對每個\(a_i\)判斷當前遞推式是否滿足條件
如果滿足就直接判斷下乙個
否則需要修改
如果當前\(\\)為空
說明\(a_i\)之前數全是\(0\)
而\(a_i\not=0\)
所以是不可能用之前的數推出\(a_i\)的
這種情況下直接把\(f_0,f_1,...f_i\)記為\(0\)
這樣\(i\le m\)就不用推了
否則說明之前已經有乙個錯誤的\(\\)
為了方便記為\(\\)
我們希望能通過\(\\)在\(i\)位推出乙個不為\(0\)的值
然後把這次的錯誤抵消掉
如果\(\\)出錯的位置是\(p\)且多了\(\delta\)
這個時候\(a_p\)一定不等於\(\sum_^f_k*a_\)
就可以對\(\\)稍作修改
在\(a_i\)的位置上遞推出乙個\(-\delta\)
具體來說
把\(\\)全部變為相反數再在最前面補\(1\)
得到的新的\(\\)可以滿足在\(p+1\)位置推出乙個\(-\delta\)來
再在\(\\)最前面補\(i-p-1\)個\(0\)
\(-\delta\)就跑到\(i\)位置來了
把現在得到的\(\\)除以\(\delta\)再乘上這次的差
加上\(\\)就可以把這次的差抵消掉
因為要求遞推式最短
我們希望每次能得到最優的\(\\)
考慮每次修改時\(\\)的長度變化
變成了\(max(len(f),len(f)+i-p)\)
所以只要記錄\(len(f)-p\)最短的\(\\)即可
還有berlekamp-massey
返回的遞推式的長度最好要在輸入的一半以內
不然還是再多打點表吧
為什麼?
感謝lhj
神仙指教
這樣多出來的一半就可以列出至少\(len(f)\)個方程組
確定了遞推式的唯一性
#includeusing namespace std;
#define ll long long
const int p=1e9+7;
inline int add(int a,int b)
inline int sub(int a,int b)
inline ll qpow(ll a,ll b)
namespace berlekampmassey
f=g;
} return f; }}
using namespace berlekampmassey;
int f=;
int main()
while(isdigit(c))x*=k;
}const int p=1e9+7;
inline int add(int a,int b)
inline int sub(int a,int b)
inline ll qpow(ll a,ll b)
namespace berlekampmassey
int ret=0;
for(int i=0;i=len(f))
f=g;
} return f; }
inline int main(const poly &a,ll n)
}int f=;
int main()
Berlekamp Massey演算法學習筆記
很久之前就聽說過這個演算法,當時六校聯考的時候day1t1是一道很有意思的遞推,神仙zzx不會做於是就拿bm演算法艹出了遞推式orzzzzzzzzzzx 推薦一篇講的詳細的不能再詳細的部落格 我就不詳細說了,只記一下自己感覺比較難理解的地方 設 r m 表示序列的遞推式且長度為 m f r,i 表示...
演算法學習 Union Find演算法
union find演算法有它的實際用途。多用於動態連通的應用場景。union find演算法是 給出兩個節點,判斷它們是否連通,如果連通,是不需要給出具體的路徑的 舉兩個例子作為主要表現 1 在網路連線中,當發現沒有連線的兩個節點,可以把他們連線起來,一旦節點都連線起來,又能把多餘的線拆除,這時候...
演算法學習 KM演算法
km演算法 用於求二分圖的最佳完美匹配 即權值最大的完美匹配 如果你也是個剛來學習km演算法的人 大概的用途肯定還是知道的吧 還是直接說重點吧 首先 理解km演算法前 必須有以下3個概念 1.可行頂標 對於乙個賦值二分圖g x,y,e,w x,y 代表二分圖的兩邊頂點標號 e代表邊 w代表邊的權值 ...