奮鬥的demon 遞推關係(理論)

2021-07-29 18:39:13 字數 3906 閱讀 8620

今天demon分析了一下之前的組隊賽,覺得有些心得:

我們這次比賽沒有關注檔案讀寫問題,導致我們一直糾結於提交出錯的情況,請你大家在比賽之前了解檔案讀寫的相關規定:是標準輸入輸出,還是檔案輸入輸出?如果是檔案輸入輸出,是否禁止用重定向方式訪問檔案?

program (重定向版)

#define local

...int main()

program (fopen版)

#include int main()

今天大白老師給demon講遞推關係了,呆萌的demon覺得很有趣,大家一起來體會遞推的樂趣吧!

問題1:兔子的繁殖。把雌雄各一的一對新兔子放入養殖場中。每對兔子從第二個月開始每月產雌雄各一的一對新兔子。試問第n個月後養殖場中共有多少對兔子?

分析:第n個月的兔子由兩部分組成,一部分是上個月就有的老兔子,一部分是剛出生的新兔子。前一部分等於f(n-1),後一部分等於f(n-2) (第n-1個月時具有生育能力的兔子數等於第n-2個月的兔子總數)。根據加法原理,f(n)=f(n-1)+f(n-2),邊界是f(1)=f(2)=1。

數列為1,1,2,3,5,8,...,稱為斐波那契(fibonacci)數列。

問題2:凸多邊形的三角剖分數。給出乙個凸n邊形,用n-3條不相交的對角線把它分成n-2個三角形,求不同的方法數目。例如n=5時,有5中剖分方法。

分析:設答案為f(n)。按照某種順序給凸多邊形的各個定點分別編號為v1,v2,...,vn。既然分成的是三角形,邊v1vn在最終的剖分中一定恰好屬於某個三角形v1vnvk,所以可以根據k進行分類。不難看出,三角形v1vnvk的左邊是乙個k邊形,右邊是乙個n-k+1邊形,根據乘法原理(參照奮鬥的demon——基本計數原理(理論)),包含三角形v1vnvk的方案數為f(k)f(n-k+1);根據加法原理有:f(n)=f(2)f(n-1)+f(3)f(n-2)+...+f(n-1)f(2),邊界是f(2)=f(3)=1。

從第三項開始的數列:1,2,5,14,42,132,429,1430,4862,16796,...,稱為卡特蘭數(catalan)。

1 通項公式:h(n)=c(n,2n)/(n+1)=(2n)!/((n!)*(n+1)!)

2遞推公式:h(n)=((4*n-2)/(n+1))*h(n-1); h(n)=h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)*h(0).

3前幾項為:h(0)=1,h(1)=1,h(2)=2,h(3)=5,h(4)=14,h(5)=42,......

4應用場景:

a.括號化問題。

矩陣鏈乘: p=a1×a2×a3×……×an,依據乘法結合律,不改變其順序,只用括號表示成對的乘積,試問有幾種括號化的方案?(h(n)種)

b.出棧次序問題。

乙個棧(無窮大)的進棧序列為1,2,3,..n,有多少個不同的出棧序列?

類似:(1)有2n個人排成一行進入劇場。入場費5元。其中只有n個人有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票,問有多少中方法使得只要有10元的人

買 票,售票處就有5元的鈔票找零?(將持5元者到達視作將5元入棧,持10元者到達視作使棧中某5元出棧)

(2)在圓上選擇2n個點,將這些點成對連線起來,使得所得到的n條線段不相交的方法數。

c.將多邊行劃分為三角形問題。

(1)將乙個凸多邊形區域分成三角形區域的方法數?

(2)類似:一位大城市的律師在她住所以北n個街區和以東n個街區處工作。每天她走2n個街區去上班。如果她從不穿越(但可以碰到)從家到辦公室的對角線,那            麼有多少條可能的道路?

(3)類似:在圓上選擇2n個點,將這些點成對連線起來使得所得到的n條線段不相交的方法數?

d.給頂節點組成二叉樹的問題。

給定n個節點,能構成多少種形狀不同的二叉樹?

(一定是二叉樹!先去乙個點作為頂點,然後左邊依次可以取0至n-1個相對應的,右邊是n-1到0個,兩兩配對相乘,就是

h(0)*h(n-1) + h(2)*h(n-2) +  + h(n-1)h(0)=h(n))(能構成h(n)個)。

問題3:用n(1≤n≤2000)根火柴棍能組成多少個非負整數?火柴不必用完,組成的整數不能有前導零(但整數0是允許的)。例如,假如有三根火柴,可以組成1或者7,假如有四根火柴,除了1和7以外,還可以組成4和11。

我們也不難知道數字0-9的火柴數:1(2),2(5),3(5),4(4),5(5),6(6),7(3),8(7),9(6),0(6)。

分析:把已經用過視為火柴數i看成乙個狀態,額可以得到乙個圖。

火柴數可能數字01

2137

4452,3,5

66,978

火柴數可能數字

x+0x+1

x+21

x+37

x+44

x+52,3,5

x+60,6,9

x+78

從前往後每新增乙個x,就從狀態i+c[i],其中c[x]代表數字x需要的火柴數。當i=0的時候不允許使用數字0。從結點0和x出發。

令d(i)為從結點0到結點i的路徑條數,而且火柴不必用完,則答案f(n)=d(1)+d(2)+d(3)+...+d(n)。

memset(d,0,sizeof(d));//d[i]為恰好用i根火柴可以i組成的正整數(不含0)

d[0] = 1;

for(int i=0;i<=maxn;i++)

for(int j=0;j<10;j++)

if(!(i==0&&j==0) && i+c[j]<=maxn) d[i+c[j]]+=d[i];//i=j=0時不允許轉移

問題4:立方數之和。輸入正整數n(n≤10000),求將n寫成若干個正整數的立方之和有多少種方法。

例如:21有2種寫法。77有22種寫法,9999有440022018293種寫法。

分析:建立多段圖。結點(i,j)表示「使用不超過i的整數的立方,累加和為j」這個狀態,設d(i,j)為從(0,0)到(i,j)的路徑條數,則最終答案為d(21,n)。

這個多段圖的特點時每個結點一步只能走到下一階段的結點,因此我們可以乙個乙個階段的計算。

memset(d,0,sizeof(d));

d[0][0] = 1;

for(int i=0;i<=maxn;i++)

for(int j=0;j對於第i個數字而言,我們可以這樣分析:如果我們取一次第i個數字得到d(i,j)那麼可以知道這是從狀態d(i,j-i^3)轉化得到;當我們不取第i個數字得到d(i,j)那麼可以知道這是從狀態d(i-1,j)轉化得到。那麼我們便可以得到遞推公式:d(i,j)=d(i-1,j)+d(i,j-i^3)(如果大家想說我們如果需要用多個i^3怎麼辦?是不是這個公式不在成立呢?仔細想想還是成立的,因為我們如果再往下遞推一層或者多層我們便可以使用多次i^3,那麼我們便可以把**寫成如下形式:時間複雜度僅僅是o(n^2),而且我們可以用滾動陣列節約儲存空間。

感覺一下這個方法和上面的演算法的對比。

#include#include#include#includeusing namespace std;

#define maxn 22*22*22

long long dp[maxn];

int main()

{ int n;

memset(dp,0,sizeof(dp));

long long c[22];

for(int i=1;i<22;i++)

c[i]=i*i*i;

dp[0]=1;

for(int i=1;i<22;i++)

for(int j=c[i];j>n)

{cout《問題5:村民排隊。村子裡現在有n(1≤n≤40000)個人,有多少種方式可以把他們排成一列,使得沒有人排在他父親的前面(有些人的父親可能不在村子裡)?輸入n和每個人的父親編號(村里的人編號為1~n),輸出方案總數除以1000000007的餘數。

分析

8 1遞推關係的運用

思路 用fn f n表示n個月後的兔子對數。轉化思想 當n 3的時候,fnfn 等於前乙個月的對數fn 1f n 1加上新出生的兔子 fn 2f n 2 f n f n f n 1 fn 1 f n 2 fn 2思路 用fn f n表示解n個盤子的漢諾塔問題所需要的移動次數。轉化思想 我們可以先用f...

理論與問題的關係

先回想一下現在數學系教科書的過程,首先介紹基本概念,其次開始提出一些公理,接著是定理的推導,以及各種結論。從頭看到尾,酣暢淋漓。但是這不是 乙個問題的方法。這些給的只是乙個巨人的肩膀。有了巨人的肩膀,我們不一定會站立,更不用說成為另外乙個巨人。我們站立的根基是前人研究的理論,但是更多時候是需要我們構...

求解分治演算法的遞推關係

相關概念 分治遞推關係 如果f n f n 表示求解規模為nn的問題所需的雲算數,則ff滿足遞推關係 f n af n b g n f n af n b g n 相關定理 定理1 設ff是滿足遞推關係 f n af n b c f n af n b c 的增函式,其中nn被bb整除,b 1,bb 1...