题面:给定一个由0~9以及?组成的字符串,其中的?可以替换成0~9中任意1个数字,问有多少种情况使得这个数字模13的余数为5?结果对1e9+7取模。注意允许s有前导0。
范围:1 <= |s| <= 1E5
分析:记dp[i][j]表示前i个数字构成的数模13余j的方案数。如果s[i]是数字,直接转移;如果是问号,枚举0~9所有可能分别转移,总时间复杂度O(13n)。这里使用的是刷表法。
#include <bits/stdc++.h>
// mint模板略
const int N = 100005;
mint dp[N][13];
void solve() {
std::string s;
std::cin >> s;
int n = s.size();
dp[0][0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j <= 12; j++) {
if (s[i] == '?') {
for (int k = 0; k <= 9; k++) {
int u = (j * 10 + k) % 13;
dp[i+1][u] += dp[i][j];
}
} else {
int k = (j * 10 + s[i] - '0') % 13;
dp[i+1][k] += dp[i][j];
}
}
std::cout << dp[n][5] << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
标签:线性dp