• 【HDU3652】B-number 数位DP


      B-number

    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
    题意:求n以内所有能被13整除且数字里包含13的数的个数
    题解:数位DP,用f[i][j][k]表示有i位,最高位为j,对13取模等于k,且数字里包含13的数的个数,g[i][j][k]表示有i位,最高位为j,对13取模等于k,且数字里包含13的数的个数。
      然后一位一位判断就可以了。
    代码
    #include <stdio.h>
    #include <string.h>
    int n,m;
    int v[20];
    int f[12][10][13],g[12][10][13],t[12];
    int main()
    {
        int i,j,k,l,ans,rem,x;
        t[1]=1;
        for(i=2;i<=10;i++)    t[i]=t[i-1]*10;
        for(i=0;i<=9;i++)    g[1][i][i]=1;
        for(i=2;i<=10;i++)
        {
            for(j=0;j<=9;j++)
            {
                for(k=0;k<=9;k++)
                {
                    for(l=0;l<=12;l++)
                    {
                        if(j==1&&k==3)
                        {
                            f[i][j][l]+=(j*t[i]+(k+1)*t[i-1]-1-l)/13-(j*t[i]+k*t[i-1]-1-l)/13;
                        }
                        else
                        {
                            f[i][j][l]+=f[i-1][k][((l-j*t[i])%13+13)%13];
                            g[i][j][l]+=g[i-1][k][((l-j*t[i])%13+13)%13];
                        }
                    }
                }
            }
        }
        while(scanf("%d",&n)!=EOF)
        {
            memset(v,0,sizeof(v));
            rem=m=ans=0;  //此时答案的后i位对13取模应该等于rem
            x=n;
            while(x)
            {
                v[++m]=x%10;
                x/=10;
            }
            for(i=m;i>=1;i--)
            {
                for(j=0;j<v[i];j++)    ans+=f[i][j][rem];
                if(v[i]>3&&v[i+1]==1)
                {
                    ans+=g[i][3][rem];
                }
                if(v[i]==3&&v[i+1]==1)
                {
                    ans+=n/13-(n/t[i]*t[i]-1)/13;
                    break;
                }
                rem=((rem-v[i]*t[i])%13+13)%13;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    | 欢迎来原网站坐坐! >原文链接<

  • 相关阅读:
    设计模式-工厂模式-场景以及优缺点-目的就是应对变化 (国江面试回答的)
    开启otl的64位长整数支持
    otl翻译(11) -- OTL的迭代器
    OTL翻译(10) -- OTL的流缓冲池
    OTL翻译(9) --常量的SQL语句
    OTL翻译(8) -- otl_long_string/otl_long_unicode_string类
    OTL翻译(7) -- otl_exception类
    OTL翻译(6) -- otl_connect类
    OTL翻译(5) -- otl_stream流相关绑定变量
    OTL翻译(4) -- otl_stream类
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6155729.html
Copyright © 2020-2023  润新知