数位DP,DP[I][J][K][L]表示到第i位,末尾为j,mod13为k,l的01表示是否出现过13了,然后就是数位DP的状态转移即可
代码:
#include <cstdio>
#include <cstring>
char num[12];
int n, dp[12][10][14][2];
int main() {
while (~scanf("%s", num)) {
n = strlen(num);
memset(dp, 0, sizeof(dp));
int pre = 0, mod = 0, flag = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
for (int x = 0; x < 13; x++) {
dp[i + 1][j][(x * 10 + j) % 13][1] += dp[i][k][x][1];
if (j == 3 && k == 1) dp[i + 1][j][(x * 10 + j) % 13][1] += dp[i][k][x][0];
else dp[i + 1][j][(x * 10 + j) % 13][0] += dp[i][k][x][0];
}
}
}
for (int j = 0; j < num[i] - '0'; j++) {
if (flag || (j == 3 && pre == 1)) dp[i + 1][j][(mod * 10 + j) % 13][1]++;
else dp[i + 1][j][(mod * 10 + j) % 13][0]++;
}
if (pre == 1 && num[i] - '0' == 3) flag = 1;
pre = num[i] - '0';
mod = (mod * 10 + num[i] - '0') % 13;
}
int ans = (flag && mod == 0);
for (int i = 0; i < 10; i++)
ans += dp[n][i][0][1];
printf("%d\n", ans);
}
return 0;
}