HDU 3485 Count 101

Count 101

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1114    Accepted Submission(s): 568

Problem 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

Source

2010 ACM-ICPC Multi-University Training Contest(5)——Host by BJTU

Recommend

zhengfeng

这个有点类似于数位DP,但是不是数位DP

设dp[i][j][k]表示长度为i串的最后两位数为i,j的不包含101的个数。

所以dp方程就有了:

dp[i][0][0]+=dp[i-1][0][1]+dp[i-1][0][0]
dp[i][0][1]+=dp[i-1][1][0]+dp[i-1][1][1]
dp[i][1][0]+=dp[i-1][0][0]
dp[i][1][1]+=dp[i-1][1][0]+dp[i-1][1][1]

最后取ans求总数就行了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int mod=9997;
const int MAXN=10000+5;
int dp[MAXN][2][2],n,ans[MAXN];

void init()
{
    memset(dp,0,sizeof(dp));
    memset(ans,0,sizeof(ans));
    ans[0]=0;ans[1]=2;ans[2]=4;
    dp[2][0][0]=dp[2][0][1]=dp[2][1][0]=dp[2][1][1]=1;
    dp[1][1][0]=dp[1][0][0]=1;
    for(int i=3;i<MAXN;i++)
    {
        dp[i][0][0]=(dp[i][0][0]+(dp[i-1][0][1]+dp[i-1][0][0])%mod)%mod;
        dp[i][0][1]=(dp[i][0][1]+(dp[i-1][1][0]+dp[i-1][1][1])%mod)%mod;
        dp[i][1][0]=(dp[i][1][0]+(dp[i-1][0][0])%mod)%mod;
        dp[i][1][1]=(dp[i][1][1]+(dp[i-1][1][0]+dp[i-1][1][1])%mod)%mod;
        ans[i]=(dp[i][0][0]+dp[i][0][1]+dp[i][1][0]+dp[i][1][1])%mod;
    }
}

int main()
{
    init();
    while(scanf("%d",&n)&&n!=-1)
    {
        printf("%d\n",ans[n]);
    }
    return 0;
}

时间: 2024-10-10 14:58:41

HDU 3485 Count 101的相关文章

HDU 3485 Count 101(递推)

C - Count 101 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3485 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 ki

hdu 1705 Count the grid(皮克定理)

题目链接:hdu 1705 Count the grid 题意: 给定一个三角形三点坐标,问三角形内有多少个坐标均为整数的点. 题解: 给定顶点坐标均是整点(或正方形格点)的简单多边形,皮克定理说明了其面积 S 和内部格点数目 n.边上格点数目 s 的关系:S = n +s/2+1 三角形两向量叉积/2=面积. 向量上整数点数为gcd(v.x,v.y)(此公式对于一条边上的结果不准确,但是三条边加在一起的和是准确的) 1 #include<bits/stdc++.h> 2 #define F(

HDU 4916 Count on the path

题意: 给定一棵树和m个询问  每个询问要求回答不在u和v两节点所形成的路径上的点的最小标号 思路: 一开始以为是LCA-  不过T了好几次-  后来发现不用LCA也可做 考虑每个询问u和v  如果他们的lca不是1  则1一定是答案  不过求lca会T  那么我们只需要在遍历树的时候给节点染色  染的颜色就是1的儿子的颜色  如果x这个点在y的子树中(y是1的儿子)那么他的颜色就是y 染完色后我们考虑答案是如何构成的 如图所示  答案即是  红色  蓝色  绿色的子树中节点的最小值  那么我们

HDU 4588 Count The Carries(找规律,模拟)

题目 大意: 求二进制的a加到b的进位数. 思路: 列出前几个2进制,找规律模拟. #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <stack> #include <vector> using namespace std; int main() { int

hdu 3336 Count the string

Count the stringTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4239    Accepted Submission(s): 1977 Problem Description It is well known that AekdyCoin is good at string problems as well as num

HDU 4588 Count The Carries 数位DP || 打表找规律

2013年南京邀请赛的铜牌题...做的很是伤心,另外有两个不太好想到的地方....a 可以等于零,另外a到b的累加和比较大,大约在2^70左右. 首先说一下解题思路. 首先统计出每一位的1的个数,然后统一进位. 设最低位为1,次低位为2,依次类推,ans[]表示这一位上有多少个1,那么有 sum += ans[i]/2,ans[i+1] += ans[i]/2; sum即为答案. 好了,现在问题转化成怎么求ans[]了. 打表查规律比较神奇,上图不说话. 打表的代码 #include <algo

hdu 3336 Count the string(KMP)

一道应用kmp算法中next数组的题目 这其中vis[i]从1加到n vis[i]=[next[i]]+1; #include<string.h> #include<stdlib.h> #include<stdio.h> #include<iostream> #include<algorithm> using namespace std; char s[200005]; int b; int next[200005]; int vis[20000

hdu 1812 Count the Tetris polya计数

哈哈哈,简单polya,公式自己推导. 不过这题需要用到大数,很久没写Java,调了好久. import java.math.*; import java.util.*; import java.io.*; public class Main{ public static void main(String args[]){ Scanner cin=new Scanner(System.in); int n; BigInteger c; while(cin.hasNextInt()) { BigI

hdu 4750 Count The Pairs 最小生成树

题意就是给出一个f值,然后假如两个点u,v间的所有路径上的最大边中的最小值大于f,那么这个点对是合法的,对于每个询问f,输出有多少个合法点对. 最大边最小就是最小瓶颈路,即最小生成树上的路径.一个简单的想法就是求出最小生成树后,n次dfs求出任意两点间的最大边,然后对于每个询问再查找一遍,可是时间复杂度太高.再想想的话会发现,两点间生成树上的最大边就是在克鲁斯卡尔的过程中使得他们第一次联通的那条边,所以,每加进一条边,以该边为最大边的点对就是他连接的两个集合的点对. #include <cstd