hdu 3652 B-number 数位dp
B-number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
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
数位dp
看的dp进阶之路
dp[i][j][k]表示第i位j状态k表示mod13的余数
j==0表示前面没有13的;
j==1表示前面一位为1;
j==2表示前面含有13;
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cmath> #include<string> #include<queue> #include<algorithm> #include<stack> #include<cstring> #include<vector> #include<list> #include<set> #include<map> using namespace std; #define ll long long #define pi (4*atan(1.0)) #define eps 1e-4 #define bug(x) cout<<"bug"<<x<<endl; const int N=2e2+10,M=1e6+10,inf=2147483647; const ll INF=1e18+10,mod=2147493647; ll bit[N]; ll f[N][5][13]; ll dp(int pos,ll pre,int flag,int m) { if(pos==0)return (pre==2&&m==0); if(flag&&f[pos][pre][m]!=-1)return f[pos][pre][m]; ll x=flag?9:bit[pos]; ll ans=0; for(ll i=0;i<=x;i++) { if(pre==2||(pre==1&&i==3)) ans+=dp(pos-1,2,flag||i<x,(m*10+i)%13); else if(i==1) ans+=dp(pos-1,1,flag||i<x,(m*10+i)%13); else ans+=dp(pos-1,0,flag||i<x,(m*10+i)%13); } return f[pos][pre][m]=ans; } ll getans(ll x) { memset(f,-1,sizeof(f)); int len=0; while(x) { bit[++len]=x%10; x/=10; } return dp(len,0,0,0); } int main() { ll n; while(~scanf("%lld",&n)) { printf("%lld\n",getans(n)); } return 0; }