数的计数(noip2001,动态规划递推)

Posted zyacmer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数的计数(noip2001,动态规划递推)相关的知识,希望对你有一定的参考价值。

题目链接:

普通版:

https://www.luogu.org/problemnew/show/P1028

数据加强版:

https://www.luogu.org/problemnew/show/P2240

中间插一段,奇怪了,我明明想到的是最好的那种递推方法,结果写着写着忘记了,写成最差的递推方法

所以中间插一段被我遗忘的好方法

这个也是这题的书上的答案

#include<bits/stdc++.h>
using namespace std;
int a[1001];
int main()
{
    int n;
    cin>>n;
    a[1]=1;
    for(int i=2;i<=n;i++)
    {
        a[i]=a[i-1];
        if(i%2==0)
            a[i]=a[i-1]+a[i/2];
    }
    cout<<a[i];
    return 0;
}

稍微解释一下:

举个例子就好了

a[5]=a[4]

a[6]=a[5]+a[6/3],那个a[6/3]就是a[3],因为相对于a[4]来说a[6]多了个a[3]的全部子数字

因为a[4]只能分解1~2

a[5]同a[4]一样

而a[6]可以分解1~3

所以a[6]多个a[3]

 

以下为自己写的垃圾方法:

基本思路:

@1:基本递推:

第n个数,它产生n/2个新的数,由于1~n/2都小于n,所以可以用递推,都计算到n了那么1~n/2的值肯定都已知了

@2:边缘条件:

我们把n=1和n=0时结果都为1都一开始就初始化好,作为初始条件

@3:细节

ps:这个地方好像有更好的办法而不是用奇葩的+1法,可是我懒得想了

在具体的数组中,a[n]应该是不包括n本身的所有子数字数目,为什么不能包括本身呢,因为后面要通过前面的数据递推

比如说a[6]=6/2 +a[1] + a[2] +a[3],那么其实是a[6]=   1+a[1]   +    1+a[2] +        1+a[3],所以最后都要加回来

@4:规律

这个结果有奇偶的规律,比如说n=3与n=2结果相同,n=19与n=18结果相同,也就是只要计算一半就好了

 

AC代码(普通版和数据加强版都适用)

#include<bits/stdc++.h>
using namespace std;
int a[1005];
int main()
{
    std::ios::sync_with_stdio(false);
    int n;cin>>n;
    if(n<=1)
    {
        cout<<0+1<<endl;
        return 0;
    }
    else
    {
        for(int i=1;i<=n+2;i++)
        {
            if(i%2==0)
            {
                a[i]=i/2;
                for(int j=1;j<=i/2;j++)
                    a[i]+=a[j];
            }
            else
                a[i]=a[i-1];
        }
    }
    if(n%2==0)
        cout<<a[n]+1<<endl;
    else
        cout<<a[n/2*2]+1<<endl;
}

 

以上是关于数的计数(noip2001,动态规划递推)的主要内容,如果未能解决你的问题,请参考以下文章

数的计数(Noip2001)

洛谷-----P1025 [NOIP2001 提高组] 数的划分

Codevs_1040_[NOIP2001]_统计单词个数_(划分型动态规划)

NOip 2012 摆花

1415.数的计数

算法:3数的计数