zoukankan      html  css  js  c++  java
  • 【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;
    }

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

  • 相关阅读:
    080626 雨(近期目标)
    6月25日 多云
    火一样的冷
    sgu107. 987654321 problem 简单打表 难度:0
    快速切题 sgu 111.Very simple problem 大数 开平方 难度:0 非java:1
    sgu114. Telecasting station 难度:1
    109. Magic of David Copperfield II 构造 难度:2
    sgu108. Selfnumbers 2 滚动数组 打表 难度:1
    快速切题 sgu115. Calendar 模拟 难度:0
    快速切题 sgu117. Counting 分解质因数
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6155729.html
Copyright © 2011-2022 走看看