YbtOJ 732 斐波那契 特徵方程,LCT

2022-07-12 05:51:10 字數 2656 閱讀 2443

給出\(n\)個點的一棵樹,以\(1\)為根,每個點有點權\(a_i\)。要求支援\(m\)次操作

修改乙個修改乙個節點的父節點

修改一條路徑的權值為\(w\)

給出\(u\)詢問\(fbi(a_u)\)

給出\(u,v\),將路徑\(u->v\)的點權排列好後設為\(b\)求

\[\sum_^k\sum_^kfbi(\sum_^jb_z)

\]其中\(fbi(i)\)表示第\(i\)個斐波那契數。輸出答案模\(998244353\)的值

\(1\leq n,m\leq 10^5,a_i,w\in[1,10^9]\)

嗯這個斐波那契很麻煩,可以考慮一些用特徵方程\(1-x-x^2=0\),可以得到斐波那契的通項公式

\[fbi(n)=\frac)^n-(\frac)^n}

\]為了方便上面\(\frac\)分別記為\(x_0,x_1\)。

那麼如果設\(c_i=x_0^,d_i=x_1^\)的話我們要求的就是

\[\frac^k\sum_^k\prod_^jc_z-\sum_^k\sum_^k\prod_^jd_z}

\]這個好像看起來好維護一點,不過首先我們要解決這個\(\sqrt 5\)的問題,因為其實\(\sqrt 5\)在模\(998244353\)意義下是沒有值的,我們不能直接用二次剩餘帶入數字。

考慮維護乙個類似於多項式的東西,每個數字記為二元組\((a,b)=a\sqrt 5+b\)。加減乘都很好搞,除法的話需要推導一下,

\[\frac=c\sqrt 5+d

\]\[5ac+\sqrt 5(ad+cb)+bd=1

\]\[5ac+bd=1,ad+cb=0

\]解出來

\[c=-\frac,d=\frac

\]這樣四則運算都搞定了,可以開始考慮如何在\(lct\)上面維護了。

類似線段樹的,設\(pro\)表示所有數乘積,\(pre/suf\)表示所有前/字尾乘積和,\(ans\)表示我們維護的答案,那麼就可以合併兩個東西了。\(lct\)維護的時候順便把單個的節點也合併進去就好了。

然後還剩下乙個最麻煩的東西就是樹鏈修改的時候我們需要快速算出連續\(x\)個\(u\)的資訊。

\(pro\)很好搞就是\(u^x\),\(suf\)和\(pre\)就是乙個簡單的等比數列求和,上通項公式就好了。

\(ans\)比較麻煩,考慮每個\(u^i\)的個數答案就是

\[\sum_^xu^i(x-i+1)=(x+1)\sum_^xu^i-\sum_^xu^ii

\]\[\rightarrow (x+1)\frac-u}-\frac-\frac}

\]這樣就可以在\(log\)時間複雜度以內合併了。

然後答案\(0\)次項一定是\(0\)的,所以輸出\(\sqrt 5\)的項就好了。

時間複雜度\(o(n\log^2 n)\)

#include#include#include#include#define ll long long

using namespace std;

const ll p=998244353,n=1e5+10;

struct node

};ll power(ll x,ll b=p-2)

return ans;

}const node x((p+1)/2,(p+1)/2);

node operator+(node x,node y)

node operator-(node x,node y)

node operator*(node x,node y)

node inv(node x)

node power(node x,ll b)

return ans;

}struct tnode;

tnode operator+(tnode x,tnode y)

struct segtree

bool direct(ll x)

void rev(ll x)

void pushup(ll x);

if(t[x][0])w[x]=w[t[x][0]]+w[x];

if(t[x][1])w[x]=w[x]+w[t[x][1]];

return;

} void updata(ll x,node u)

void pushdown(ll x)

if(!r[x])return;

rev(t[x][0]);rev(t[x][1]);

r[x]=0;return;

} void rotate(ll x)

void splay(ll x)

return;

} void access(ll x)

void makeroot(ll x)

void link(ll x,ll y)

ll split(ll x,ll y)

void change(ll x,ll y,node val)

}t;ll n,m;

signed main()

for(ll i=2;i<=n;i++)

scanf("%lld",&t.fa[i]);

while(m--)

else if(op==2)

else if(op==3)

else if(op==4)

} return 0;

}

斐波那契數列 斐波那契數列python實現

斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家列昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 1 1 2 3 5 8 13 21 34 在數學上,斐波納契數列以如下被以遞推的方法定義 f 1 ...

迴圈斐波那契數列 斐波那契數列應用

什麼是斐波那契數列 斐波那契數列指的是這樣乙個數列 1,1,2,3,5,8,13,21,34,55,89,144 這個數列從第3項開始,每一項都等於前兩項之和 台階問題 有一段樓梯有10級台階,規定每一步只能跨一級或兩級,要登上第10級台階有幾種不同的走法?這就是乙個斐波那契數列 登上第一級台階有一...

斐波那契堆

以下是實現的程式 肯定可以再優化的。include include include include using namespace std class node delete m child m child null class fibonacciheap node insert int key v...