HDU3652 B-number数位DP

B n u m b e r B-number

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9715 Accepted Submission(s): 5821

Problem Description8
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

第二道数位DP的题,题意很简单,输入一个数n,要求x ∈ [ 0, n ],满足:x中含有能整除13并且x中含有"13",输出满足条件的x的数量。就是这里的约束条件有两个,所以我们用于记忆化搜索的dp数组要设置为三维的。dp[ i ][ j ][ k ] 表示当前数位为i,j为当前位之前的各位和对13取模的值,k表示x中含有"1",或者"13"或者都没有。当当前位为-1,也就是所有位都枚举完了,如果枚举出来的数满足条件的话,就可以计数1,否则计数0。

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 20;
int n;
int dp[maxn][13][3];        //前位和对13取模是多少 上一位是否为1   dp用来记录之前的状态
int num[maxn];				//记录各位数字
int dfs(int pos,int modsum,int isone,bool limit){
    if(pos==-1) return (modsum==0)&&(isone==2);		//如果满足条件就计数
    if(!limit&&dp[pos][modsum][isone]!=-1) return dp[pos][modsum][isone];
    int ans = 0; int up = limit ? num[pos] : 9;		//判断是否前面都取最大值
    for(int i=0;i<=up;i++){
        int tmpmod = (modsum*10+i)%13;				//加上当前之后的余数
        int tmpisone = isone;						//如果已经存在"13"就可以直接继续搜索了
        if(isone==0&&i==1) tmpisone = 1;
        else if(isone==1&&i==3) tmpisone = 2;
        else if(isone==1&&i!=1) tmpisone = 0;
        ans+=dfs(pos-1,tmpmod,tmpisone,limit&&(i==num[pos]));
    }
    if(!limit) dp[pos][modsum][isone] = ans;
    return ans;
}
int solve(int x){
    int pos = 0;
    while(x){
        num[pos++] = x%10;
        x/=10;
    }
    int res = dfs(pos-1,0,0,true);
    return res;
}
int main(){
    memset(dp,255,sizeof(dp));
    while(scanf("%d",&n)!=EOF){
        printf("%d\n",solve(n));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43710979/article/details/89191558