HDU 3652 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
Author
wqb0039
Source
Recommend
lcy
题目大意:
给定一个数n,问你 1~n 有多少个数本身既是13的倍数,且数位中含有13
解题思路:
很明显是数位DP,用 长度,是否包含13,前一个数位,以及对13求余后的余数 这四维来表示DP的状态。
解题代码:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <sstream> using namespace std; int dp[11][2][15][15]; const int w[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000}; string st; int DP(int len,int f,int pre,int left){ if(len==0){ if(f==1 && left==0 ) return 1; else return 0; } if(dp[len][f][pre][left]!=-1) return dp[len][f][pre][left]; int ans=0; for(int i=0;i<=9;i++){ if(i==3 && pre==1 ) ans+=DP(len-1,1,i,(left+w[len-1]*i)%13 ); else ans+=DP(len-1,f,i,(left+w[len-1]*i)%13 ); } return dp[len][f][pre][left]=ans; } int dfs(int len,int f,int pre,int left){ if(len<=0){ if(f==1 && left==0 ) return 1; else return 0; } int x=st[st.length()-len]-'0'; int ans=0; for(int i=0;i<x;i++){ if(pre==1 && i==3) ans+=DP(len-1,1,i,( left+ i*w[len-1])%13 ); else ans+=DP(len-1,f,i,( left+ i*w[len-1])%13 ); } if(pre==1 && x==3) ans+=dfs(len-1,1,x, ( left+ x*w[len-1])%13 ); else ans+=dfs(len-1,f,x, ( left+ x*w[len-1])%13 ); return ans; } int main(){ int n; memset(dp,-1,sizeof(dp)); while(cin>>n){ stringstream ss; ss<<n; ss>>st; cout<<dfs(st.length(),0,0,0)<<endl; } return 0; }