Time limit 1000 ms
Memory limit 32768 kB
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.
题目分析
B-number B数,比较套路的入门数位DP
d
p
[
i
]
[
m
o
d
]
[
s
t
]
dp[i][mod][st]
dp[i][mod][st]表示 当前还剩
i
i
i位没填,除以13余数为mod
st=0表示13还没出现过;st=1表示13没出现过且第
i
+
1
i+1
i+1位为1;st=2表示13出现过
的满足条件的数字个数
套上数位DP的记搜板就好了
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=50;
int n;
int dp[maxn][15][5],dig[maxn];
int qpow(int a,int k,int p)
{
int res=1;
while(k>0){
if(k&1) res=(res*a)%p;
a=(a*a)%p; k>>=1;
}
return res;
}
int DP(int len,int mod,int st,int pre)
{
if(len==0) return (mod==0&&st==2);
if(!pre&&dp[len][mod][st]!=-1) return dp[len][mod][st];
int res=0,mx=pre?dig[len]:9;
for(int i=0;i<=mx;++i)
{
int nxt;
if(st==2||(st==1&&i==3)) nxt=2;
else if((st==0||st==1)&&i==1) nxt=1;
else nxt=0;
res+=DP(len-1,(mod+qpow(10,len,13)*i)%13,nxt,pre&&i==mx);
}
if(!pre) dp[len][mod][st]=res;
return res;
}
int solve(int x)
{
int len=0;
while(x)
{
dig[++len]=x%10;
x/=10;
}
return DP(len,0,0,1);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(dp,-1,sizeof(dp));
printf("%d\n",solve(n));
}
return 0;
}