• HDU 3652 B-number(数位DP)


    题意:问你1到n中间有多少数包含13的子串,并且是13的倍数

    思路:我们很容易想到,一个数是不是13的倍数,只需要进行同余模定理就可以了,然后在设置一个标志存储是否含有13的串,(我觉得这样做真的没有什么问题,但在记录答案的时候会多记录),然后我们说正确的状态怎么定义其实是多了一个位置,把刚才的标志改为3个状态,一个代表包含13,一个代表已1结尾,一个代表没有

    代码:(聚聚们如果知道为什么两个状态会多记录答案,方便的话在下面留言,教教小弟)

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    int a[55];
    LL dp[55][20][5];
    
    LL dfs(int pos,int m,int ok,bool limit)
    {
    //    printf("test pos==%d pre==%d m==%d ok==%d limit==%d
    ",pos,pre,m,ok,limit);
        if(pos==-1){
            return m==0&&ok==2;
        }
        if(!limit&&dp[pos][m][ok]!=-1) return dp[pos][m][ok];
        int up=limit?a[pos]:9;
        LL ans=0;
    //    printf("qqq pos==%d up==%d
    ",pos,up);
        for(int i=0;i<=up;i++){
            int mx=(m*10+i)%13;
            int as=ok;
            if(ok==0&&i==1)as=1;
            if(ok==1&&i!=1)as=0;
            if(ok==1&&i==3)as=2;
            ans+=dfs(pos-1,mx,as,limit&&i==a[pos]);
        }
    //    printf("zzz ans==%lld
    ",ans);
        if(!limit)dp[pos][m][ok]=ans;
    //    printf("end pos==%d pre==%d m==%d ok==%d limit==%d
    ",pos,pre,m,ok,limit);
        return ans;
    }
    LL solve(int x)
    {
        int pos=0;
        while(x){
            a[pos++]=x%10;
            x/=10;
        }
        return dfs(pos-1,0,0,true);
    }
    int main()
    {
        LL n;
        memset(dp,-1,sizeof(dp));
        while(~scanf("%d",&n)){
            printf("%lld
    ",solve(n));
        }
        return 0;
    }
    /*
    
    13
    */
  • 相关阅读:
    Alpha冲刺第一天
    团队项目-需求分析
    设计模式第二次作业
    设计模式第一次作业
    冲刺合集
    冲刺NO.12
    项目测试
    冲刺NO.11
    冲刺NO.9
    冲刺NO.10
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9950770.html
Copyright © 2020-2023  润新知