2 条题解

  • 3
    @ 2023-11-26 10:13:47

    首先看一下试题:

    我们要求找出具有下列性质数的个数(包含输入的正整数 n)。

    先输入一个正整数 n(n≤1000),然后对此正整数按照如下方法进行处理:

    不作任何处理;
    
    在它的左边拼接一个正整数,但该正整数不能超过原数,或者是上一个被拼接的数的一半;
    
    加上数后,继续按此规则进行处理,直到不能再加正整数为止。
    输入格式
    
    1个正整数 n(n≤1000)
    输出格式
    
    1个整数,表示具有该性质数的个数。
    输入输出样例
    

    输入:6 输出:6 说明/提示

    满足条件的数为

    6,16,26,126,36,136

    【题目来源】

    NOIP 2001 普及组第一题

    上面的就是题目内容,那么现在我们来分析一下这道题是什么意思:

    首先给出一个数为n,我们需要在它的左边不断加数直到不能加为止,求出这个过程中出现的(诞生的)所有的数的个数。

    那么我们可以发现:边界条件在这里发挥着重要的作用,我们不妨从边界条件下手,看一看到底什么时候“它的左边不断加数直到不能加”即可。

    我们不妨先举几个例子:

    1->1//只有一种情况,为1

    2->2->12//有两种情况,分别是2,12

    3->3->13//有两种情况,分别是3,13

    4->14

    4->24->124//共四种情况,分别是4,14,24,124

    你应该已经发现规律了吧!

    我们已经发现,这道题应该可以用递推来做,那么我们来思考递推式应如何推导:

    假定已经输入一个数n,我们按照要求看一看

    不作任何处理;
    
    在它的左边拼接一个正整数,但该正整数不能超过原数,或者是上一个被拼接的数的一半;
    
    加上数后,继续按此规则进行处理,直到不能再加正整数为止。
    

    1.不做任何处理,则有f(n)judge1=1(第一判断有1种情况)

    2.拼数,我们直接看可以拼上多少个数,就应该有多少种情况

    根据我们上面的举例以及题目意思,各位应该可以发现,n前面是可以拼floor(n/2)个数的,至于为什么向下取整,是因为不能超过上一个被拼接的数的一半

    然而我们还不知道n前面这floor(n/2)个数每个数执行步骤“3”怎么算对吧,那么我们思考:这floor(n/2)个数分别代表的数是什么呢?没错,就是从1到floor(n/2)之间所有的正整数对吧!所以呢,我们就可以轻而易举地找出第二步与第三步结合起来形成的递推式啦:f[n]judge2,3=f[1]+f[2]+......+f[n/2]//这里之所以我不加floor取整,是因为c++语言中整型数据类型会自动向下取整

    那么整个的递推式就把它们加起来就好了!即:f[n]=f[n]judge1+f[n]judge2,3=1+f[1]+f[2]+......+f[n/2]//这里不加floor也是一个道理

    那么最后码一下就可以了

    AOJ不能用LATEX挺讨厌的,大家可以看我发布的原文,格式更好看些:https://blog.csdn.net/lishuhang_zy/article/details/122998742?spm=1001.2014.3001.5502

  • 0
    @ 2024-11-26 13:21:44

    注意! 样例输出的是方案总数而不是处理后的n

    • 1

    信息

    ID
    107
    时间
    1000ms
    内存
    125MiB
    难度
    3
    标签
    递交数
    58
    已通过
    31
    上传者