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
13 100 200 1000
Sample Output
1 1 2 2
Author
wqb0039
Source
【题意】:计算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:有13
int 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,所以变为1
if(have==1&&i!=1)have_=2;//前一位是1,现在不是1,还需下一步判断是不是3
if(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));
}
}