dp uestc L 菲波拉契數制公升級版

2022-04-04 11:12:44 字數 1964 閱讀 3302

資料很大,以揹包的思路陣列開不下。

先定序地考慮乙個菲波拉契數如fib(i)的表示法,假設i比較大,由菲波拉契數的定義可知道fib(i)=fib(i-1)+fib(i-2);要找到其它表示就繼續拆分fib(i-1)或fib(i-2),假如拆分fib(i-1)得到fib(i)=2*fib(i-2)+fib(i-3),這不能保證保證互不相同的性質(補充,也許有人會考慮將這個式作為中間過程通過拆出矛盾項來保證唯一性,然而消除了乙個矛盾必然產生新的矛盾,所以不行,具體地說將fib(i-2)=fib(i-3)+fib(i-4)消除了fib(i-2)的矛盾然而產生了fib(i-3)的矛盾,fib(i-3)又是由fib(i-1)得來,無法通過有限次拆分將矛盾消除),因此考慮拆fib(i-2),又得到一種表達方式fib(i)=fib(i-1)+fib(i-3)+fib(i-4);繼續拆分,和前面類似,只能拆fib(i-4);不難發現每次只能拆最小的fib數,終點為fib(1)或fib(2);由上面過程可以得出:1或2+2*m=i,m是除了fib(i)本身以外其他的表示方法,上式可以得出m=(i-1)/2(/都表示向下取整,下同)。

ok,我們成功地解決了n為菲波拉契數的情況;下面考慮n為菲波拉契數的組合的情況;假設n=fib(i)+fib(j),i>j;我們知道fib(i)和fib(j)單獨的情況,現在組合起來可以借鑑剛剛拆分的思想,不同的是現在可能fib(i)和fib(j)都可以拆分;假設拆分fib(j)(可能你要問,為什麼要拆小的那個?原因是在fib(i)拆分中會有和fib(j)拆分衝突的情況)得到(j-1)/2+1組;現在考慮拆fib(i),和一開始一樣的思想只是終點發生了變化,為確定終點(保證獨立性),我們考察fib(j)的拆分情況,我們發現在(j-1)/2種拆分中都是以fib(j-1)開頭的,因此終點為fib(j)或fib(j+1),可以得到等式2*m1+j或(j+1)=i,m1=(i-j)/2,m1是除了fib(i)本身以外其他的表示方法;以fib(j)開頭,即fib(j)本身,終點為fib(j+1)或fib(j+2),m2=(i-j-1)/2,m2是除了fib(i)本身以外其他的表示方法。綜上,含fib(i)的表示有(j-1)/2+1種,不含fib(i)的表示有m1*(j-1)/2+m2。現在推廣到n=fib(i)+fib(j)+fib(k),i>j>k的情況fib(j)和fib(k)的組合已經知道了,而且分兩組以fib(j)開頭的和以fib(j-1)開頭的,對fib(i)拆分和上一種辦法一樣,由此給出dp[i][0]的定義:以fib(i-1)開頭的所有組合,dp[i][1]:以fib(i)開頭的所有組合。於是有狀態轉移方程dp[i][1]=dp[j][0]+dp[j][1],dp[i][0]=(i-j-1)/2*dp[j][1]+(i-j)/2*dp[j][0],最終結果為dp[maxi][0]+dp[maxi][1]。

#include #include 

#include

using

namespace

std;

long

long

int dp[88][2];//

dp[i][0] 表示comb[0~i]的所有組合的降序排列中以fib[i-1]開頭的 [1]表示以fib[i]開頭的

long

long

int fib[88

];void

get_fibs()

vector

comb;//

組成n的fib的下標

long

long

intn;

void

solve()

sort(comb.begin(),comb.end());

dp[0][1]=1

; dp[

0][0]=comb[0]/2

;

for(int i=1;i)

printf(

"%lld\n

",dp[comb.size()-1][1]+dp[comb.size()-1][0

]);}

intmain()

return0;

}

UESTC 菲波拉契數制

一維的01揹包 include include include include include include include include include define fop freopen in r stdin define inf 0x3f3f3f3f define ll int64 de...

UESTC1133 菲波拉契數制 01揹包思想

description 我們定義如下數列為菲波拉契數列 f 1 1 f 2 2 f i f i 1 f i 2 i 3 給定任意乙個數,我們可以把它表示成若干互不相同的菲波拉契數之和。比如13 有三種表示法13 13 13 5 813 2 3 8 現在給你乙個數n 請輸出把它表示成若干互不相同的菲波...

菲波那契數列

菲波那契數列是指這樣的數列 數列的第乙個和第二個數都為1,接下來每個數都等於前面2個數之和。給出乙個正整數k,要求菲波那契數列中第k個數是多少。1 遞迴演算法 include define m 99 int main scanf d k for i 2 i k 1 i printf d n a k ...