1363: Count 101 (经典数位dp)

本文探讨了一种使用动态规划方法解决特定序列计数问题的策略,即计算长度为n且不含子串101的所有可能二进制序列的数量。通过定义三个状态(以0结尾、以1结尾、任意结尾),文章详细阐述了状态转移方程,并提供了完整的代码实现。

1363: Count 101

Submit Page    Summary    Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 393     Solved: 154    


Description

You know YaoYao is fond of his chains. He has a lot of chains and each chain has n diamonds on it. There are two kinds of diamonds, labeled 0 and 1. We can write down the label of diamonds on a chain. So each chain can be written as a sequence consisting of 0 and 1.
We know that chains are different with each other. And their length is exactly n. And what’s more, each chain sequence doesn’t contain “101” as a substring.
Could you tell how many chains will YaoYao have at most?

Input

There will be multiple test cases in a test data. For each test case, there is only one number n(n<10000). The end of the input is indicated by a -1, which should not be processed as a case.

Output

For each test case, only one line with a number indicating the total number of chains YaoYao can have at most of length n. The answer should be print after module 9997.

Sample Input

3
4
-1

Sample Output

7
12

Hint

We can see when the length equals to 4. We can have those chains:
0000,0001,0010,0011
0100,0110,0111,1000
1001,1100,1110,1111

 

给你长度为n的序列,只能由0或者1组成
不能出现101,问你这样序列的个数
分析:
数位dp
可以由很多dp方式,比如三维dp
做过一个非常类似的题
dp1[i]:表示长度为i的满足要求的(不出现101)的以0结尾的方案数
dp2[i]:表示长度为i的满足要求的(不出现101)的以1结尾的方案数目
dp3[i]:表示长度为i的满足要求的以(1或者0)结尾的方案数目
dp3[i]=dp1[i]+dp2[i];
所以我们只需要得的dp1和dp2的转移方程
dp1:
想一下dp1[i]的含义(以0结尾)
因为题目要求是没有101
所以对dp1,第i位置
前面的第i-1位置可以是0,可以是1
所以:dp1[i]=dp1[i-1]+dp2[i-1]
dp2:
想一下dp2[i]的含义(以1结尾)
题目要求没有101
对dp2的第i位置
所以肯定第i位置肯定是1(dp2的含义)
所以前面的第i-1个位置也只能是1
前面的第i-2个位置也只能是0
这样才不会有101出现
所以:
dp2[i]=dp2[i-1]+dp1[i-2]
所以通过dp1和dp2,我们就可以知道dp3了
注意:记得dp的初始化
其实还可以用斐波那契写,听学弟说的....
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<memory.h>
#include<memory>
using namespace std;
#define max_v 10005
#define mod 9997
int dp1[max_v];
int dp2[max_v];
int dp3[max_v];
int main()
{
    dp1[1]=1;
    dp1[2]=2;

    dp2[1]=1;
    dp2[2]=2;

    dp3[1]=dp1[1]+dp2[1];
    dp3[2]=dp1[2]+dp2[2];
    for(int i=3;i<10000;i++)
    {
        dp1[i]=(dp1[i-1]+dp2[i-1])%mod;
        dp2[i]=(dp1[i-2]+dp2[i-1])%mod;
        dp3[i]=(dp1[i]+dp2[i])%mod;
    }

    int n;
    while(~scanf("%d",&n))
    {
        if(n<0)
            break;
        printf("%d\n",dp3[n]);
    }
    return 0;
}
/*
给你长度为n的序列,只能由0或者1组成
不能出现101,问你这样序列的个数

分析:
数位dp
可以由很多dp方式,比如三维dp
做过一个非常类似的题
dp1[i]:表示长度为i的满足要求的(不出现101)的以0结尾的方案数
dp2[i]:表示长度为i的满足要求的(不出现101)的以1结尾的方案数目
dp3[i]:表示长度为i的满足要求的以(1或者0)结尾的方案数目

dp3[i]=dp1[i]+dp2[i];

所以我们只需要得的dp1和dp2的转移方程
dp1:
想一下dp1[i]的含义(以0结尾)
因为题目要求是没有101
所以对dp1,第i位置
前面的第i-1位置可以是0,可以是1
所以:dp1[i]=dp1[i-1]+dp2[i-1]

dp2:
想一下dp2[i]的含义(以1结尾)
题目要求没有101
对dp2的第i位置
所以肯定第i位置肯定是1(dp2的含义)
所以前面的第i-1个位置也只能是1
前面的第i-2个位置也只能是0
这样才不会有101出现
所以:
dp2[i]=dp2[i-1]+dp1[i-2]

所以通过dp1和dp2,我们就可以知道dp3了

注意:记得dp的初始化

其实还可以用斐波那契写,听学弟说的....

*/

 

转载于:https://www.cnblogs.com/yinbiao/p/9487884.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值