• 递推


    HDU 2044 "一只小蜜蜂"

    •题解

      类似与斐波那契数列;

      定义 $f[i]$ 表示从 $1$ 号蜂房走到 $i$ 号蜂房的总方案数,那么有 $f[1]=f[2]=1$,$f[i]=f[i-1]+f[i-2] , i > 2$;

      但此题要求你从 $a$ 号蜂房走到 $b$ 号蜂房的总方案数;

      那么,你就需要将 $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
    ",f[b]);
    21     }
    22     return 0;
    23 }
    View Code

    •变形

      题面不变,数据加强;

      令 $0<a<ble 100000$,并要求最终答案对 $1e9+7$ 取模;

    •分析

      对变形前代码时间复杂度分析的话,最坏的情况是,$O(Tcdot 50)$,当然,如果 $T < 10^6$ 还是可以过得;

      但是,加大数据后,这可就不一定了;

      考虑到每次测试数据中的 $for$ 循环,可不可以提前预处理出来;

      如果 $a=1$ ,那么,斐波那契数列第 $b$ 项 $f[b]$ 就是答案;

      如果 $a oe 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
    ",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 imes f[i-2]$;

      所以,$f[i]=f[i-1]+2 imes 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
    ",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
    ",f[n][m]);
    26     }
    27 }
    View Code
  • 相关阅读:
    laravel的workflow流程插件
    [php]laravel框架容器管理的一些要点
    laravel 自带消息notification通知
    laravel5.5的定时任务详解(demo)
    Laravel核心代码学习
    laravel 加载指定版本的mongodb
    Linux安装Composer
    composer全量镜像使用方法
    laravel在github地址
    node anyproxy ssi简易支持
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/11787795.html
Copyright © 2020-2023  润新知