B-number (HDU-3652)数位DP

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

题意:问你在1到给定的n的范围之间,有多少个能被13整除的数。
思路:数位DP模板题,取余的时候用秦九韶算法。
           nstate: 0:不含13, 1:不含13但末尾是1, 2 :含13
AC代码:

#include <bits/stdc++.h>
typedef long long ll;
const int maxx=100;
const int inf=0x3f3f3f3f;
using namespace std;
ll a[maxx];
ll dp[maxx][maxx][maxx];
ll dfs(int pos,int mod,int state,bool limit)
{
    if(pos==-1)
        return mod==0 && state==2;
    if(!limit &&dp[pos][mod][state]!=-1)
        return dp[pos][mod][state];
    ll ans=0;
    int up=limit?a[pos]:9;
    for(int i=0; i<=up; i++)
    {
        int nmod=(mod*10+i)%13;
        int nstate=state;
        if(state==0 && i==1)//高位不含13,并且末尾不是1,现在末尾添1返回1状态
            nstate=1;
        else if(state==1 && i!=1 && i!=3)//高位不含13,且末尾是1,现在末尾添加的不是1返回0状态
            nstate=0;
        else if(state==1 && i==3)//高位不含13,且末尾是1,现在末尾添加3返回2状态
            nstate=2;
        ans+=dfs(pos-1,nmod,nstate,limit && i==a[pos]);
    }
    if(!limit)
        dp[pos][mod][state]=ans;
    return ans;
}
ll solve(ll x)
{
    int pos=0;
    while(x)
    {
        a[pos++]=x%10;
        x/=10;
    }
    return dfs(pos-1,0,0,true);
}
int main()
{
    ll n;
    memset(dp,-1,sizeof(dp));
    while(~scanf("%lld",&n))
    {
        printf("%lld\n",solve(n));
    }
    return 0;
}
发布了204 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43846139/article/details/103925114