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
题意:问你在1到给定的n的范围之间,有多少个能被13整除的数。
思路:数位DP模板题,取余的时候用秦九韶算法。
nstate: 0:不含13, 1:不含13但末尾是1, 2 :含13
AC代码:
#include <bits/stdc++.h>
typedef long long ll;
const int maxx=100;
const int inf=0x3f3f3f3f;
using namespace std;
ll a[maxx];
ll dp[maxx][maxx][maxx];
ll dfs(int pos,int mod,int state,bool limit)
{
if(pos==-1)
return mod==0 && state==2;
if(!limit &&dp[pos][mod][state]!=-1)
return dp[pos][mod][state];
ll ans=0;
int up=limit?a[pos]:9;
for(int i=0; i<=up; i++)
{
int nmod=(mod*10+i)%13;
int nstate=state;
if(state==0 && i==1)//高位不含13,并且末尾不是1,现在末尾添1返回1状态
nstate=1;
else if(state==1 && i!=1 && i!=3)//高位不含13,且末尾是1,现在末尾添加的不是1返回0状态
nstate=0;
else if(state==1 && i==3)//高位不含13,且末尾是1,现在末尾添加3返回2状态
nstate=2;
ans+=dfs(pos-1,nmod,nstate,limit && i==a[pos]);
}
if(!limit)
dp[pos][mod][state]=ans;
return ans;
}
ll solve(ll x)
{
int pos=0;
while(x)
{
a[pos++]=x%10;
x/=10;
}
return dfs(pos-1,0,0,true);
}
int main()
{
ll n;
memset(dp,-1,sizeof(dp));
while(~scanf("%lld",&n))
{
printf("%lld\n",solve(n));
}
return 0;
}