• hdu3652 B-number(数位dp)


    Problem Description
    A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string “13” and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n.

    Input
    Process till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000).

    Output
    Print each answer in a single line.

    Sample Input
    13
    100
    200
    1000

    Sample Output
    1
    1
    2
    2

    分析:
    题目大意就是找到一些数字,能被13整除,同时数字中还要出现13

    看起来是道数位dp
    但是这个%13==0的限制有点烦
    有点像啊

    现在进入了看每道题都觉得有以前做过的题的影子,
    这就进入了刷题第二阶段之似懂非懂
    只有继续修炼,才能从似懂非懂上升到看出算法

    是否能整除十三好像有一个简便算法:

    先划去这个数的末一位数,
    然后用剩余数字所表示的数加上所划数的4倍,
    不断地重复这一操作,直到数字变成一个两位数
    如果最后得到的数能被13整除,那么,这个数就能被13整除


    这个数的末三位数与末三位以前的数字所组成的数之差能被13整除, 那么原数就可以被13整除

    f[i][j][k][0/1][0/1] //第i位是j,第i-1位是k,数字中有没有13,是否卡边界
    这样可以很简单的转移出满足第二个条件的数字
    然并卵
    看到网上的前辈说随便搞,我就有点害怕

    于是就想了一个状态:
    f[i][j][k][0/1][0/1] //第i位是j,当前数字%13的余数,数字中有没有13,是否卡边界
    事实证明,这是正确的O(∩_∩)O~

    tip

    不要忘了初始化
    今天状态真的不大好:
    两处手残查了半个小时,而且全都是初始化写错:
    这里写图片描述

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    int n,len,a[20],b[20];
    int f[20][11][20][2][2];
    
    int doit()
    {
        int i,j,k,l,s,c;
        memset(f,0,sizeof(f));
        for (i=0;i<=a[1];i++) f[1][i][i%13][0][i==a[1]]=1;   //
        for (i=1;i<len;i++)
            for (j=0;j<=9;j++)
                for (k=0;k<13;k++)
                    for (l=0;l<=1;l++)
                        for (s=0;s<=1;s++)
                        if (f[i][j][k][l][s])
                        {
                            int tt=9;
                            if (s) tt=a[i+1];
                            for (c=0;c<=tt;c++)
                            {
                                int x=(k*10)%13+c;
                                x%=13;
                                f[i+1][c][x][l|(j==1&&c==3)][s&(c==a[i+1])]+=f[i][j][k][l][s];
                            }
                        }
        int ans=0;
        for (i=0;i<=9;i++)
            for (j=0;j<=1;j++)
                ans+=f[len][i][0][1][j];
        return ans;
    }
    
    int main()
    {
        while (scanf("%d",&n)!=EOF)
        {
            len=0;
            while (n)
            {
                len++;
                b[len]=n%10;
                n/=10;
            }
            for (int i=1;i<=len;i++) a[i]=b[len-i+1];
            printf("%d
    ",doit());
        }
        return 0;
    } 
  • 相关阅读:
    mysql的导出与导入命令的使用
    kendo ui 左侧弹出分享框
    Pytorch离线安装方法
    Python单词接龙小程序
    Shell结束指定名称的进程
    Shell脚本sed命令修改文件的某一行
    Shell中单双引号的区别
    矩阵问题
    泛型通配符详解
    合并链表
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673171.html
Copyright © 2020-2023  润新知