加個斐波那契數列

2022-09-23 03:15:13 字數 3042 閱讀 2084

題意

有 \(n(\leq3\times 10^5)\) 個點的樹, \(m(\leq3\times 10^5)\) 個詢問。

對 與\(x\) 點距離 \(\leq d\) 的 \(y\) 點加上 \(f_(x,y)}\), 其中 \(f_0 = a, f_1 = b, f_i = f_ + f_(i\geq 2)\)。

詢問 \(u\) 點的權值,對 \(10^9 + 7\) 取模。

斐波那契數列性質

先不考慮距離限制。

令 \(f_0 = 0, f_1 = 1, f_i = f_ + f_ (i\geq 2)\), 特別的,令 \(f_ = -1, f_ = 1\)。

那麼對於任意 \(n \geq 0\), 都有\(f_n = b \times f_ + a \times f_\)。

斐波那契數列有這樣一條性質:

\[f_n = f_f + f_f

\]轉換一下,對於一條 \(u\) 到 \(v\) 長 \(\text\) 的路徑,可以拆分成 \(u\) 到 \(\text(u,v)\) 的路徑, 長 \(\text_1\),和 \(v\) 到 \(\text(u,v)\) 的路徑, 長 \(\text_2\)。

其中 \(\text = \text_1 + \text_2\)。

那麼上面的式子就可以寫成,

\[f_} = f__1 - 1} f__2} + f__2 + 1}f__1}

\]因此對於詢問點 \(u\) 的值,可以列舉祖宗,來列舉經過該點的路徑,換句話說,就是列舉路徑的 lca。

然後預處理另一半的路徑,就能快速計算價值,修改操作具有可加性。

具體來說,對於要點 \(u\) 加的 \(f_n\) 拆開。

因為:\[f_n = b \times f_n + a \times f_

\]所以:

\[f_} = b \times ( f__1 - 1}f__2} + f__2 + 1}f__1}) + a \times (f__1 - 2} f__2} + f__2 + 1}f__1 - 1} )

\]\[f_} = (b \times f__1 - 1} + a \times f__1 - 2})f__2} + (b \times f__1} + a \times f__1 - 1})f__2 + 1}

\]只要在每個點維護兩個括號裡面的和,只要有乙個點的距離 \(\text_2\) 就能快速求出所有修改的值的和。

具體來說:

修改操作,對於點 \(x\) 到根的點加上兩個括號的和。

詢問操作,對點 \(x\) 到根的點查詢所有的和。

這樣的一次的時間複雜度是樹高\(\times\)詢問複雜度

點分樹對於 「距離 \(\leq d\) 的點」 這樣與樹的形態無關的限制,一般都要用樹分治,比如點分治。

這裡有修改操作,於是使用點分樹。

點分樹的樹高是 \(\log n\) 級別的,對於每個點維護樹狀陣列,一次詢問就是 \(o(\log n)\) 的。

由於求和時會算重,一般都要維護兩個樹狀陣列,當前節點的貢獻和對家長的貢獻,在詢問時相減。

**:

#includeusing namespace std;

using ll = long long;

const int maxn = 300010;

const int inf = 0x7fffffff;

const int mod = 1000000007;

template void read(t &x)

int add(int a, int b)

int mul(int a, int b)

int n, m;

int f[maxn], *f = f + 3;

vectore[maxn];

struct tree1

} int top[maxn];

void dfs2(int u, int tp)

} int lca(int x, int y)

if (dep[x] > dep[y]) swap(x, y);

return x;

} int distan(int x, int y)

} t;

struct node

node operator +(const node &x) const

node operator -(const node &x) const

};struct tree2

void add(int x, node val)

node query(int x)

node query(int x, int y)

} t1[maxn], t2[maxn];

int s, mi, root;

int mx[maxn], siz[maxn];

bool vis[maxn];

void getroot(int u, int fa)

mx[u] = max(mx[u], s - siz[u]);

if (mx[u] < mi) mi = mx[u], root = u;

}int fa[maxn];

void build(int u)

}node calc(int a, int b, int dis)

void change(int u, int d, int a, int b)

}int calc2(node x, int dis)

int query(int u)

return ans;

}void init(int n)

int main()

init(n);

t.dfs1(1, 0);

t.dfs2(1, 1);

s = n, mi = inf, root = - 1;

getroot(1, 0);

build(root);

while (m --) else

} 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級台階有幾種不同的走法?這就是乙個斐波那契數列 登上第一級台階有一...

斐波那契數列

1 題目描述 大家都知道斐波那契數列,現在要求輸入乙個整數n,請你輸出斐波那契數列的第n項。斐波那契數列的定義如下 輸入 輸入可能包含多個測試樣例,對於每個測試案例,輸入包括乙個整數n 1 n 70 輸出 對應每個測試案例,輸出第n項斐波那契數列的值。2 這是九度上的乙個題,要求時間限制1秒,整數的...