码迷,mamicode.com
首页 > 其他好文 > 详细

【hdu3652】B-number 数位DP

时间:2016-12-10 15:58:56      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:ati   color   std   single   output   scanf   ble   nbsp   bre   

  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

标签:ati   color   std   single   output   scanf   ble   nbsp   bre   

原文地址:http://www.cnblogs.com/CQzhangyu/p/6155729.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!