zoukankan      html  css  js  c++  java
  • 序列计数

    蓝桥杯快来了,给大家分享一道蓝桥杯的题目


    题目

    小明想知道,满足以下条件的正整数序列的数量

    1. 第一项为 n;
    2. 第二项不超过 n;
    3. 从第三项开始,每一项小于前两项的差的绝对值。
      请计算,对于给定的 n,有多少种满足条件的序列。
      【输入格式】
      输入一行包含一个整数 n。
      【输出格式】
      输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。

    【样例输入】
    4
    【样例输出】
    7
    【样例说明】
    以下是满足条件的序列:
    4 1
    4 1 1
    4 1 2
    4 2
    4 2 1
    4 3
    4 4
    【评测用例规模与约定】
    对于 20% 的评测用例,1 <= n <= 5;
    对于 50% 的评测用例,1 <= n <= 10;
    对于 80% 的评测用例,1 <= n <= 100;
    对于所有评测用例,1 <= n <= 1000。

    题解基本思路(看了大家的一些题解,总觉得有些复杂~~)

    • 首先从样例输出来看,该序列的长度至少为2

    • 用递归枚举的方法来做这道题肯定是很耗时的,所以采用一点动态规划的思想

    • First, 先考虑长度为2的序列, n1 n2;类似于 1 1,2 1, 2 2这样。

    • Second, 我们考虑长度为3的序列,从样例来看,类似于 4 1 1, 4 2 1,4 1 2 这样的序列;我们只需观察该序列中的2,3两位,你会发现有熟悉 1 1, 2 1,他们属于我们n=1,n=2中符合条件的序列,也就是First中的情况;但是,你也会发现这里误入了一个 1 2,它似乎就让我们有点陌生了。

    • Then,我们在考虑长度为4的序列... 哈哈哈,皮一下,其实我们考虑以上两种情况就足以了。

    Summarize

    • 刚刚只是给大家引了下路,这里给大家举个例子,对于给定的数字n,我用f(a,b)表示序列以a,b开头的序列的个数,如f(1,1)=1, f(4,1)=3,这个可以简单的笔算出来。

    • 规律就是,如果我们想知道所有 以5 2 ...开头的序列的个数,我们是不是只需要知道以2 1, 2,2开头的序列的个数和就行了呢?(因为从第三项开始,每一项小于前两项的差的绝对值)而要知道 2 1, 2,2开头序列的个数,就可以从第一步轻松得到;即使上升一个较大的数值n,我们也能够递推至最小的子问题,只要我们将每种不同开头的个数储存起来,就能避免很多的重复运算,接着往下看.

    • 在用二维数组处理时,我们假设 1 2( 1 4)这样特殊的"开头"的序列存在,他们用来储存 n3<n2 时对应序列的值,这样就可以和上面统一了。对于如何得到这个值,如求1 4 这样开头的序列,我们只需在多处理一步,就又变成了4 1, 4 2这样我们熟悉的处理了。

    python代码实现

    def list_count(n):  
      '''
            动态规划: 构建 (n+1)*(n+1)整形矩阵
            buf[i][j]: (i>=1, j>=1) 表示 i,j..开头的序列
            4 1 2 3
            n1 n2 n3 n4
            由题:n1 > n2, n3<|n1 -n2|
            假设,如果将n1去掉后:n2,n3,n4 也满足要求
            此时存在情况:
            1:
                n2=n3, buf[n1][n2]=1
            2: 
                n2>n3, buf[n1][n2]=buf[n2][1]+...+buf[n2][ni] (1<i<n2-n3-1)
            3: 
                n2<n3,取|n2-n3|, buf[n1][n2]=buf[n3][1]+...+buf[n3][ni] (1<i<|n2-n3|)
        '''
      
      buf=[[0 for _ in range(0,n+1)] for _ in range(0,n+1)]
      for i in range(1,n+1):
          for j in range(1,i+1):
            #主处理
              if i-j>1:
                  buf[i][j]+=1
                  for k in range(1,i-j):
                      buf[i][j]+=buf[j][k]
              else:
                  buf[i][j]+=1
              buf[i][j]%=10000
             #辅助处理,计算n3<n2时的值
          for x in range(1,i):
              buf[x][i]+=1
              for y in range(1, abs(x-i)):
                  buf[x][i]+=buf[i][y]
    
      return sum(buf[n])%10000
    

    如图:n=5时,buf的值为:

    此方阵可以得到所有i<=n的结果,对buf[i]求和

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    dba_segments和dba_tables的不同
    查询用户表空间
    远程登录Oracle数据库
    SQL Server 收缩数据库
    Xshell乱码解决方法设置
    Spring常用注解
    Hibernate的fetch
    在 Eclipse 中使用 JSHint 检查 JavaScript 代码
    enterprise architect (EA) 源码生成UML类图,帮助理解项目工程
    上传excel数据到数据库中
  • 原文地址:https://www.cnblogs.com/hongbo-tao/p/14667259.html
Copyright © 2011-2022 走看看