HDOJ 3555 Bomb (按位DP)

题目大意:求1到n中有多少个数含“49”

第一次接触按位DP,参考了别人的题解。

第一个代码运行速度快些(31ms),但状态的转移的分析比较麻烦,第二个代码要慢些(125ms),但code比较方便。

View Code
#include <stdio.h>

#include <string.h>

#define LEN 22

typedef __int64 LL;

char s[LEN];

LL dp[LEN][3][2];

int next(int cur,int in)

{

    if(cur==2 || cur==1&&in==9) return 2;

    return in==4;

}

LL DP(char s[],int len)

{

    memset(dp,0,sizeof(dp));

    dp[0][0][1]=1;

    for(int i=1;i<=len;i++)

    {

        dp[i][0][0]=9*dp[i-1][0][0]+8*dp[i-1][1][0];

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

        dp[i][2][0]=10*dp[i-1][2][0]+dp[i-1][1][0];



        for(int j=0;j<s[i]-'0';j++)

        {

            dp[i][next(0,j)][0]+=dp[i-1][0][1];

            dp[i][next(1,j)][0]+=dp[i-1][1][1];

            dp[i][next(2,j)][0]+=dp[i-1][2][1];

        }



        dp[i][next(0,s[i]-'0')][1]+=dp[i-1][0][1];

        dp[i][next(1,s[i]-'0')][1]+=dp[i-1][1][1];

        dp[i][next(2,s[i]-'0')][1]+=dp[i-1][2][1];

    }

    return dp[len][2][0]+dp[len][2][1];

}

int main()

{

    int t;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%s",s+1);

        printf("%I64d\n",DP(s,strlen(s+1)));

    }

    return 0;

}

 

View Code
#include <stdio.h>

#include <string.h>

#define LEN 22

typedef __int64 LL;

char s[LEN];

LL dp[LEN][3][2];

int nextstate(int cur,int in)

{

    if(cur==2 || cur==1&&in==9) return 2;

    return in==4;

}

int nextflag(int cur,int in,int max)

{

    if(cur==1 && in==max)   return 1;

    if(cur==1 && in>max)    return -1;

    return 0;

}

LL DP(char s[],int len)

{

    memset(dp,0,sizeof(dp));

    dp[0][0][1]=1;

    for(int i=1;i<=len;i++)

    {

        for(int state=0;state<3;state++)

        {

            for(int flag=0;flag<2;flag++)

            {

                for(int j=0;j<10;j++)

                {

                    if(nextflag(flag,j,s[i]-'0')==-1)   continue;

                    dp[i][nextstate(state,j)][nextflag(flag,j,s[i]-'0')]+=dp[i-1][state][flag];

                }

            }

        }

    }

    return dp[len][2][0]+dp[len][2][1];

}

int main()

{

    freopen("in.txt","r",stdin);

    int t;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%s",s+1);

        printf("%I64d\n",DP(s,strlen(s+1)));

    }

    return 0;

}

 

你可能感兴趣的:(bom)