遞推

 

 

HDU 2044 "一隻小蜜蜂"

•題解

  相似與斐波那契數列;php

  定義 $f[i]$ 表示從 $1$ 號蜂房走到 $i$ 號蜂房的總方案數,那麼有 $f[1]=f[2]=1$,$f[i]=f[i-1]+f[i-2]\ ,\ i > 2$;c++

  但此題要求你從 $a$ 號蜂房走到 $b$ 號蜂房的總方案數;ide

  那麼,你就須要將 $a$ 號蜂房設置爲 $1$ 號蜂房便可,即令 $f[a]=f[a+1]=1$,$f[i]=f[i-1]+f[i-2]\ ,\ i > a+1$;測試

  輸出 $f[b]$ 便可;大數據

•Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 
 5 int a,b;
 6 ll f[100];
 7 
 8 int main()
 9 {
10     int T;
11     scanf("%d",&T);
12     while(T--)
13     {
14         scanf("%d%d",&a,&b);
15         f[a]=1;
16         f[a+1]=1;
17         for(int i=a+2;i <= b;++i)
18             f[i]=f[i-1]+f[i-2];
19 
20         printf("%lld\n",f[b]);
21     }
22     return 0;
23 }
View Code

•變形

  題面不變,數據增強;spa

  令 $0<a<b\le 100000$,並要求最終答案對 $1e9+7$ 取模;code

•分析

  對變形前代碼時間複雜度分析的話,最壞的狀況是,$O(T\cdot 50)$,固然,若是 $T < 10^6$ 仍是能夠過得;blog

  可是,加大數據後,這可就不必定了;get

  考慮到每次測試數據中的 $for$ 循環,可不能夠提早預處理出來;it

  若是 $a=1$ ,那麼,斐波那契數列第 $b$ 項 $f[b]$ 就是答案;

  若是 $a \noe 1$ 呢?

  咱們考慮一下比以前多計算的狀況;

  首先,在以前的代碼中,每次都令 $g[a]=g[a+1]=1$;(爲不與斐波那契 $f$ 混淆,如下將上題中的 $f$ 改成 $g$)

  也就是說,$f[a]$ 比 $g[a]$ 多計算了 $f[a]-1$ 中狀況,一樣,$f[a+1]$ 比 $g[a]$ 多計算了 $f[a+1]-1$ 中狀況;

  定義 $x=f[a]-1\ ,\ y=f[a+1]-1$,那麼,由遞推式 $g[a+2]=g[a+1]+g[a]$ 可得 $f[a+2]$ 比 $g[a+2]$ 多計算了 $x+y$;

  也就是說,$f[b]$ 比 $g[b]$ 多計算的東西與 $a,b$ 之間的距離有關;

  定義 $X[i]\ ,\ Y[i]$ 分別表示從 $a$ 蜂房到 $b$ 蜂房多計算了 $X[i]$ 個 $x$ 和 $Y[i]$ 個 $y$ 值;

  那麼,只須要從 $f[b]$ 中減掉就好了;

•Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int N=1e5+50;
 5 const int MOD=1e9+7;
 6 
 7 int a,b;
 8 ll x[N];
 9 ll y[N];
10 ll f[N];
11 
12 void Init()
13 {
14     x[0]=y[1]=1;
15     y[0]=x[1]=0;
16     for(int i=2;i < N;++i)
17     {
18         x[i]=x[i-1]+x[i-2];
19         y[i]=y[i-1]+y[i-2];
20         x[i] %= MOD;
21         y[i] %= MOD;
22     }
23     f[1]=f[2]=1;
24     for(int i=3;i < N;++i)
25         f[i]=(f[i-1]+f[i-2])%MOD;
26 }
27 int main()
28 {
29     Init();
30 
31     int T;
32     scanf("%d",&T);
33     while(T--)
34     {
35         scanf("%d%d",&a,&b);
36         ll u=f[a]-1;
37         ll v=f[a+1]-1;
38         ll ans=f[b]-(u*x[b-a]%MOD+v*y[b-a]%MOD)%MOD;
39         ans=(ans+MOD)%MOD;
40 
41         printf("%lld\n",ans);
42     }
43 
44     return 0;
45 }
View Code

 

 

 


HDU 2045

•題意

  有排成一行的n個方格,用紅(Red)、粉(Pink)、綠(Green) 三色塗每一個格子;

  每格塗一色,要求任何相鄰的方格不能同色,且首尾兩格也不一樣色;

  求所有的知足要求的塗法;

•題解(遞推)

  定義 $f[i]$ 表示 $i$ 個格子的總方案數;

  假設 $f[1],f[2],\cdots ,f[i-1]$ 已經求出,如何求出 $f[i]$ 呢?

  考慮到這一點 $i$ 與 $i-1$ 不一樣色,同時 $i$ 與 $1$ 也不一樣色;

  $i$ 個格子的總方案數是否是能夠分爲如下兩種:

  ① 第 $i-1$ 個格子與第 $1$ 個格子不一樣色

  ② 第 $i-1$ 個格子與第 $1$ 個格子同色

  對於狀況①,已知 $f[i-1]$ 求解的是 $i-1$ 與 $1$ 不一樣色的總方案數,因此,狀況①的答案爲 $f[i-1]$;

  對於狀況②,由於第 $i-1$ 個格子與第 $1$ 個格子同色,且第 $i-1$ 個格子與第 $i-2$ 個格子不一樣色;

  也就是說,求解第 $i-1$ 個格子與第 $1$ 個格子同色的總方案數能夠轉化爲求解第 $i-2$ 個格子與第 $1$ 個格子不一樣色的總方案數;

  易得 $f[i-2]$ 就是解,又由於第 $i-1$ 個格子與第 $1$ 個格子同色,因此,第 $i$ 個格子有兩種選擇;

  因此狀況②的總方案數爲 $2\times f[i-2]$;

  因此,$f[i]=f[i-1]+2\times f[i-2]$;

•Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int N=60;
 5 
 6 int n;
 7 ll f[N];
 8 
 9 int main()
10 {
11     f[1]=3;
12     f[2]=f[3]=6;
13     for(int i=4;i < N;++i)
14         f[i]=f[i-1]+2*f[i-2];
15 
16     while(~scanf("%d",&n))
17         printf("%lld\n",f[n]);
18 }
View Code

 


HDU 2049 "不容易系列之(4)——考新郎"

•題解

  定義 $f[i][j]$ 表示 $i$ 對新婚夫婦中,$j$ 個新郎找錯新娘的總方案數;

  假設 $i-1$ 對新婚夫婦的全部新郎找錯新娘的總方案數已經求出;

  那麼,若是如今又來了一對新婚夫婦,如何求解這 $i$ 對新婚夫婦中全部新郎找錯新娘的總方案數呢?

  以求解 $f[i][j]$ 爲例;

  考慮到如下幾種狀況:

    • 前 $i-1$ 對新婚夫婦中有 $j$ 個新郎找不到新娘,那麼,第 $i$ 個新郎必定找對了新娘
    • 前 $i-1$ 對新婚夫婦中有 $j-1$ 個新郎找不到新娘,那麼,第 $i$ 個新郎勢必要與前 $i-1$ 對新婚夫婦中找不到新娘的新郎互換新娘才知足 $j$ 個新郎找不到新娘的條件
    • 前 $i-1$ 對新婚夫婦中有 $j-2$ 個新郎找不到新娘,那麼,第 $i$ 個新郎勢必要與前 $i-1$ 對新婚夫婦中找到新娘的新郎互換新娘才知足 $j$ 個新郎找不到新娘的條件
  • 狀況 1 的總方案數爲 $f[i-1][j]$
  • 狀況 2 的總方案數爲 $f[i-1][j-1]\cdot (j-1)$,第 $i$ 個新郎與這 $j-1$ 個找不到新娘的新郎中的任意一個新郎互換新娘均可以知足條件
  • 狀況 3 的總方案數爲 $f[i-1][j-2]\cdot (i-j+1)$,第 $i$ 個新郎與找到新娘的新郎中的任意一個互換新娘均可以知足條件

  綜上,$f[i][j]=f[i-1][j]+f[i-1][j-1]\cdot (j-1)+f[i-1][j-2]\cdot (i-j+1)$ ;

•Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int N=21;
 5 
 6 int n,m;
 7 ll f[N][N];
 8 
 9 void Init()
10 {
11     for(int i=1;i < N;++i)
12         f[i][0]=1;
13     for(int i=2;i < N;++i)
14         for(int j=2;j <= i;++j)
15             f[i][j]=f[i-1][j]+(j-1)*f[i-1][j-1]+(i+1-j)*f[i-1][j-2];
16 }
17 int main()
18 {
19     Init();
20     int T;
21     scanf("%d",&T);
22     while(T--)
23     {
24         scanf("%d%d",&n,&m);
25         printf("%lld\n",f[n][m]);
26     }
27 }
View Code
相關文章
相關標籤/搜索