HDU3652 B-number 数位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.
InputProcess till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000).OutputPrint each answer in a single line.Sample Input
13
100
200
1000
Sample Output
1
1
2
2
心里没有点13数吗,233?
第一次提交代码:
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define LL long long const int N=20; int dp[N][N][2][2][2],n; int a[N],cnt; void _divide(LL v){ cnt=0; while(v){a[++cnt]=v%10;v/=10;} } int _dfs(int pos,int Mod,bool limit,bool pre,bool stat) { if(pos==0) return stat&&!Mod; int tmp=0; if(!limit&&dp[pos][Mod][limit][pre][stat]) return dp[pos][Mod][limit][pre][stat]; int Up=limit?a[pos]:9; for(int i=0;i<=Up;i++) tmp+=_dfs(pos-1,(Mod*10+i)%13,limit&&i==Up,i==1,stat||(pre&&i==3)); dp[pos][Mod][limit][pre][stat]=tmp; return tmp; } int main() { int i,T; while(~scanf("%d",&n)){ memset(dp,0,sizeof(dp)); _divide(n); printf("%d\n",_dfs(cnt,0,true,false,false)); } return 0; }
时间长,是因为memset次数太多。
优化:去掉memset,加上limit限制
第二次提交代码:
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define LL long long const int N=20; int dp[N][N][2][2][2],n; int a[N],cnt; void _divide(LL v){ cnt=0; while(v){a[++cnt]=v%10;v/=10;} } int _dfs(int pos,int Mod,bool limit,bool pre,bool stat) { if(pos==0) return stat&&!Mod; int tmp=0; if(!limit&&dp[pos][Mod][limit][pre][stat]) return dp[pos][Mod][limit][pre][stat]; int Up=limit?a[pos]:9; for(int i=0;i<=Up;i++) tmp+=_dfs(pos-1,(Mod*10+i)%13,limit&&i==Up,i==1,stat||(pre&&i==3)); dp[pos][Mod][limit][pre][stat]=tmp; return tmp; } int main() { int i,T; while(~scanf("%d",&n)){ _divide(n); printf("%d\n",_dfs(cnt,0,true,false,false)); } return 0; }
It is your time to fight!