HDU 3652 B-number(数位DP+记忆化搜索)

来源:互联网 发布:杨紫整了哪里知乎 编辑:程序博客网 时间:2024/05/27 09:48

B-number

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


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
131002001000
 

Sample Output
1122
 

Author
wqb0039
 

Source
2010 Asia Regional Chengdu Site —— Online Contest 

【题意】:计算1到n的范围内有几个含13,并整除13的数

【思路】:典型数位DP,没什么好说的 ,使用记忆化深搜来记录状态,配合数位DP来解决

【trick】:

【代码】:
#include<stdio.h>#include<iostream>#include<string>#include<string.h>#include<cstdlib>#include<algorithm>#include<map>#include<cmath>#include<stack>#include<queue>#include<set>#include<vector>#define F first#define S second#define PI acos(-1.0)#define E  exp(1.0)#define INF 0xFFFFFFF#define MAX -INF#define len(a) (__int64)strlen(a)#define mem0(a) (memset(a,0,sizeof(a)))#define mem1(a) (memset(a,-1,sizeof(a)))using namespace std;template<class T> T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}template<class T> T lcm(T a, T b) {return a / gcd(a, b) * b;}template<class T> inline T Min(T a, T b) {return a < b ? a : b;}template<class T> inline T Max(T a, T b) {return a > b ? a : b;}int digit[15];int dp[10][15][5];//pos 第pos位//mod 余数//have  1:有1  2:没1   3:有13int dfs(int pos,int mod,int have,int lim){if(pos<=0)return mod==0&&have==3;if(!lim&&dp[pos][mod][have]!=-1)return dp[pos][mod][have];int num=lim?digit[pos]:9;int ans=0;for(int i=0;i<=num;i++)//枚举第pos位{int have_=have;int mod_=(mod*10+i)%13;if(have==2&&i==1)have_=1;//前一位不是1,该位是1,所以变为1if(have==1&&i!=1)have_=2;//前一位是1,现在不是1,还需下一步判断是不是3if(have==1&&i==3)have_=3;ans+=dfs(pos-1,mod_,have_,lim&&i==num);}if(!lim)dp[pos][mod][have]=ans;return ans;}int main() {//freopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);int n;while (scanf("%d", &n) != EOF) {mem1(dp);mem0(digit);int len=0;while(n){digit[++len]=n%10;n/=10;}printf("%d\n",dfs(len,0,2,1));}}


0 0