Description
王女士是一个数学爱好者,这些天她对B数很感兴趣。
B数的定义:能被13整除且本身包含字符串"13"的数。
例如:130和2613是B数,但是143和2639不是B数。
你的任务是计算1到n之间有多少个数是B数。
输入数据只有一个数,为n。(1<=N<=10^15)
Solution
数位dp显然。我们记f[i,j,k,0/1]为前i位,模13余j,最后一位为k,是否出现了13的方案数
原谅我只会搜索版本的数位dp,不过应该够用了(flag
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fill(x,t) memset(x,t,sizeof(x))
typedef long long LL;
LL f[31][14][10][2][2];
int a[31];
void dfs(int dep,int sum,int last,bool thir,bool lim) {
if (dep==a[0]+1) {
f[dep][sum][last][thir][lim]=(thir&&sum==0);
return ;
}
if (f[dep][sum][last][thir][lim]) return ;
int up=(lim)?(a[dep]):9;
rep(i,0,up) {
dfs(dep+1,(sum*10+i)%13,i,thir|(last==1&&i==3),lim&(i==up));
f[dep][sum][last][thir][lim]+=f[dep+1][(sum*10+i)%13][i][thir|(last==1&&i==3)][lim&(i==up)];
}
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
LL n,ans=0; scanf("%lld",&n); n;
do {a[++a[0]]=n%10;} while (n/=10);
rep(i,1,a[0]/2) std:: swap(a[i],a[a[0]-i+1]);
rep(i,1,a[1]) {
fill(f,0);
dfs(2,i,i,0,i==a[1]); ans+=f[2][i][i][0][i==a[1]];
}
rep(st,2,a[0]) {
rep(i,1,9) {
fill(f,0);
dfs(st+1,i,i,0,0); ans+=f[st+1][i][i][0][0];
}
}
printf("%lld\n", ans);
return 0;
}