首页 > 代码库 > 【hdu3652】B-number 数位DP

【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\n",ans);
    }
    return 0;
}

 

【hdu3652】B-number 数位DP