HDU 3652 B-number【数位DP】

B-number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8313 Accepted Submission(s): 4931

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

Author
wqb0039

Source
2010 Asia Regional Chengdu Site —— Online Contest

Recommend

相比普通的数位DP,多一维来保存余数。

#include<bits/stdc++.h>

using namespace std;
const int maxn=2e3+45;
const int INF=0x3f3f3f3f;
#define charmax(x,y) x=max(x,y)
#define charmin(x,y) x=min(x,y)
#define clr(x,p) memset(x,p,sizeof x)
int n;
int s[15];int k=0;
int dp[15][15][4];
int dfs(int pos,int have,int lim,int mod_x){
    int num;int mod;int hvt;
    if(pos<=0){
        return mod_x==0&&have==3;
    }
    if(!lim&&dp[pos][mod_x][have]!=-1) return dp[pos][mod_x][have];
    num=lim?s[pos]:9;int ans=0;
    for(int i=0;i<=num;i++){
        //int ans=0;
        hvt=have;
        mod=(mod_x*10+i)%13;
        if(hvt==0&&i==1){//have 0 number
            hvt=1;
        }
        if(hvt==1&&i==3){// have 1 number
            hvt=3;
        }
        if(hvt==1&&i!=1){// have b number
            hvt=0;
        }
        ans+=dfs(pos-1,hvt,lim&&num==i,mod);
    }
    if(!lim) dp[pos][mod_x][have]=ans;
    return ans;
}
int main()
{
    while(~scanf("%d",&n)){
    k=0;
    clr(s,0);
    while(n>0){
        s[++k]=n%10;
        n=n/10;
    }
    /*for(int i=0;i<k;i++){
        swap(s[i],s[k-i-1]);
    }*/
    clr(dp,-1);
    int ans=dfs(k,0,1,0);
    printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/irish_moonshine/article/details/81152901