相当于对 求[1, n]中包含13的数字 这个问题多加了一个限制,要求被13整除。
于是改写原来的状态 f(k, i, j, l) 前面两维依旧,以i开头位数为k。j取1 or 0,表示是否包含13,l 取 [0, 13) 表示MOD13后余数为l。
在计数的时候,还要维护一个变量,用来表示前面的数位是否包含13,因为这里不像只需要判断是否包含13的情况,现在不能直接break。
同时可以维护一个mod, 表示前面的高位与n相同,后面取0的数MOD13的结果。这样枚举l的时候,便可以直接 (mod+l)%13 得到整个数MOD13的值。
int f[11][11][13][2], d[11], b[11], n;
int solve() {
int len = 0;
while (n) {
d[len++] = n%10;n /= 10;
}
d[len] = 0;
b[1] = 1;
for (int i=2;i<=len;++i) b[i] = b[i-1]*10%13;
int m = 0, flag = 0, ans = 0;
for (int i=len-1;i>=0;--i) {
for (int j=0;j<d[i];++j) {
int tmp = (13 - m)%13;
ans += f[i+1][j][tmp][1];
if (flag || d[i+1] == 1 && j == 3) {
ans += f[i+1][j][tmp][0];
}
}
if (d[i+1] == 1 && d[i] == 3) flag = 1;
m = (m+d[i]*b[i+1])%13;
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
#endif
//SPEED_UP
while (cin >> n) {
memset(f, 0, sizeof(f));
f[0][0][0][0] = 1;
int base = 1;
for (int i=1;i<=10;++i) {
for (int j=0;j<10;++j)
for (int k=0;k<10;++k)
for (int l=0;l<13;++l) {
int tmp = (l+j*base)%13;
if (j == 1 && k == 3) {
f[i][j][tmp][1] += f[i-1][k][l][0] + f[i-1][k][l][1];
}
else {
f[i][j][tmp][0] += f[i-1][k][l][0];
f[i][j][tmp][1] += f[i-1][k][l][1];
}
}
base *= 10;base %= 13;
}
n += 1;
cout << solve() << endl;
}
return 0;
}