题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3652
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
题意:
给出一个数N,问1~N这N个数中,含有“13”并且能被13整除的数(例如13,1313,2613)有多少个。
题解:
N达到1e9,使用数位DP;
(做了许多数位DP了,题解什么的不想再仔细写了,建议在有数位DP基础的情况下阅读以下内容)
dfs(pos, mod, pre, have13, limit):
①pos,不讲了……
②mod,表示之前位除以13所得的余数;
③pre,记录前一位;
④have13,记录曾经是否出现过“13”;
⑤limit,不讲了……
dp数组直接无修改记忆化:即定义为dp[pos][mod][pre][have13],空间管够~
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int dig[12]; ll dp[12][13][10][2]; ll N; ll dfs(int pos,int mod,int pre,bool have13,bool limit) { if(pos==0) return have13 && mod==0; if(!limit && dp[pos][mod][pre][have13]!=-1) return dp[pos][mod][pre][have13]; int up=limit?dig[pos]:9; ll ans=0; for(int i=0;i<=up;i++) { if(pre==1 && i==3) ans+=dfs(pos-1,(mod*10+i)%13,i,1,limit && i==up); else ans+=dfs(pos-1,(mod*10+i)%13,i,have13,limit && i==up); } if(!limit) dp[pos][mod][pre][have13]=ans; return ans; } ll solve(ll x) { int len=0; while(x) { dig[++len]=x%10; x/=10; } return dfs(len,0,0,0,1); } int main() { while(scanf("%I64d",&N)!=EOF) { memset(dp,-1,sizeof(dp)); printf("%I64d\n",solve(N)); } }