QOJ #1280.Fibonacci Partition/Fibonacci性質大雜燴

Imcaigou發表於2024-04-05

QOJ #1280.Fibonacci Partition

(為什麼佈置的作業題沒有任何可見 AC 記錄啊/kk)

拿下了 QOJ 上的使用者首殺(同時目前也是 QOJ 可見的 submission 中唯一一個過掉這個題的,另一個是 vjudge 上我的提交)。

也許是這個題實在是太冷門了,但是從 Fibonacci-Lucas 數列的性質應用上是一道非常有意義的題。

題意

有一個 \(X\) 初始為 \(0\),進行 \(m\) 次操作。每次操作 \(X\leftarrow X+a\cdot F_b\),其中 \(b\) 為第 \(b\) 項 Fibonacci 數(這裡的 Fibonacci 數列的定義與之前不同,\(F_1=1,F_2=2\))。每次操作後輸出一個數 \(\lambda(X)\),其中 \(\lambda(x)\) 表示 \(x\) 最多可以表示成多少項不同的 Fibonacci 數之和。

\(|a|,b\le10^9,m\le5\times 10^4\)

Sol

我們欽定 Fibonacci 數列為如下定義:

\[F_0 = 0, F_1=1,F_n=F_{n-1}+F_{n-2}\\ F_{-n}=(-1)^{n+1}F_n\\ n>0 \]

這樣的定義使得對於任意一個整數 \(x\) 都滿足 \(F_x=F_{x-1}+F_{x-2}\),是一個十分優雅的擴充套件定義。

但是下文所有有關分解或者表示法都只包括 \(n>1\) 的項。

Zeckendorf theorem, Zeckendorf's representation

描述

任意正整數都有且僅有一種方法,可以表示成若干在數列上不連續的 Fibonacci 數的和,且不包括 \(F_1\)

證明

存在性

通常的方法是使用一種構造方法。

令正整數為 \(x\)

從大到小列舉每個 Fibonacci 數,如果 \(F_i\le x\),則 \(x\leftarrow x-F_i\)

然後我們透過歸納來證明。

有命題:\(\forall x : x<F_i\)\(x\) 一定可以被 \(F_2,F_3,\cdots,F_{i-1}\) 中不連續的一些數表出。

假設此命題對於 \(i\) 即以前的數成立,目前我們有 \(F_i\le x<F_{i+1}\)\(F_i\le x<F_i+F_{i-1}\)

我們要將這個命題推向 \(i+1\),因此我們考慮 \(x'\leftarrow x-F_i\),因此得到 \(x'<F_{i-1}\),所以 \(x\) 可以表示為 \(F_i+x'\),而 \(x'\) 可以被表示為 \(F_2,F_3,\cdots,F_{i-2}\) 中不連續的數之和。

因此我們透過歸納證明出了存在性。

唯一性

仍然透過上述的構造方法證明。

考慮如果要不同於上述構造的結果,那麼必定有一個 \(F_i\le x\) 的時刻並沒有令 \(x\leftarrow x-F_i\),因此我們只需要證明 \(\forall x : x\ge F_i\) 一定不能被表示成 \(F_{i-1},F_{i-2},\cdots,F_2\) 中不連續的數的和即可。

那麼可知的是,表示的最大數應該為 \(F_i+F_{i-2}+\cdots+[2\mid i]F_2+[2\nmid i]F_3\)

會發現無論什麼情況,只要把這個數加上 \(1\),就可以從最後一個數往前合併,最後得到 \(F_i\),因此上式應該等於 \(F_i-1\)

因此 \(\forall x:x\ge F_i\) 一定不能被表示成 \(F_{i-1},F_{i-2},\cdots,F_2\) 中不連續的數的和。

\(\Box\)

性質

容易證明 Zeckendorf's representation 一定是項數最少的分解。

而且另外一件關於這道題的性質是從這個分解到題目要求的最大分解的轉化。

我們可以發現如下的轉化一定是滿足題目要求的:

10000101001 (Zeckendorf's representation)
10011001001
11101001001
11101110001
11101110110 (Answer)

因此我們得到已知 Zeckendorf's representation 時的一個計算貢獻的方法。

  • 初始有 \(ans=0,las=1\),記 \(p_i\) 表示第 \(i\) 項分解。
  • 對於 \(p_i - las < 3\) 時,\(las\leftarrow p_i,\; ans\leftarrow ans+1\)
  • 對於 \(p_i-las\ge 3\) 時,\(las\leftarrow p_i-1,ans\leftarrow ans+\left\lceil\frac{p_i-las}{2}\right\rceil\)

Fibonacci-Lucas 數列

我們定義 Lucas 數列:

\[L_0=2,L_1=1,L_n=L_{n-1}+L_{n-2} \]

結論

\[L_k\cdot F_n=F_{n+k}+(-1)^kF_{n-k} \]

證明

歸納法證明。當 \(k=0,1\) 時顯然成立。

假設結論在 \(\forall k' : k'<k\) 成立,則應有:

\[L_{k-1}\cdot F_n=F_{n+k-1}+(-1)^{k-1}F_{n-k+1} \\ L_{k-2}\cdot F_n=F_{n+k-2}+(-1)^{k-2}F_{n-k+2} \]

直接將兩式相加得到:

\[(L_{k-1}+L_{k-2})\cdot F_n=(F_{n+k-1}+F_{n+k-2})+(-1)^k(F_{n-k+2}-F_{n-k+1}) \\ L_k\cdot F_n=F_{n+k}+(-1)^k F_{n-k} \]

\(\Box\)

用途

透過與 Zeckendorf's representation 相同的構造方法可以證明任何正整數都有 Lucas 數列上的分解(但不一定不連續)。記得只剩 \(L_0,L_1\) 時應該先考慮 \(L_0\) 再考慮 \(L_1\),因為 \(L_0>L_1\)

因此題面中的 \(a\cdot F_b\) 可以轉化成嚴格小於 \(2\log_2 a\) 項 Fibonacci 數之和,因此我們只需要維護 \(X\leftarrow X\pm F_y\) 即可。

資料結構維護

考慮維護 \(X\) 的 Zeckendorf's representation。

具體來說會發現不管是計算貢獻還是加入,連續的 \(10\) 串形如 \(1010101\) 是會被連帶影響的,因此使用 ODT 或普通平衡樹維護即可。

發現可以分類討論加入的情況:

  • \(00101010100\to 01101010100\) 的情況可以得到 \(00000000010\)
  • \(00101010100\to 00101110100\) 的情況可以得到 \(00101000010\)
  • \(00101010100\to 00101020100\) 的情況可以得到 \(11111110100\) 進而得到 \(10010100010\)
  • 減法的 \(0(-1)00000\) 可以變成 \(1111\cdots 10(-1)\) ,因此往前找到第一個 \(1\) 去掉,這個 \(1\) 一定時存在的,然後把後面的連續的 \(1\) 變成 \(1010\cdots\) 的形態。

非常繁瑣,因此實現較為複雜,應該有更好的實現。

時間複雜度 \(O(n\log_2^2 V)\)\(V\) 為值域。

Code

Submission #372257 - QOJ.ac

相關文章