[题解] HDU7060 Separated Number 思路整理
题目链接
题目大意
给一个
做法
枚举数位,计算每个数位的贡献。
令这个
设
- 当
且 时,该段左右两边都有其他段,所以相当于余下的 位中插入了一块隔板,方案数为 。 - 当
且 时,没有剩下的数,方案数为 。 - 当
或 时( 、 不同时等于 ),那么只有一边有段,方案即为 。
加起来即为答案。
不妨设:
那么:
不难求出
由定义可以发现
是 ~ 选不超过 个位置的方案数,也是 ~ 选不超过 个位置的方案数。- 两区间相加,重叠部分为
、 位置都不选, ~ 选不超过 个位置的方案数,即 。 - 缺少部分为
、 位置都选, ~ 选不超过 个位置的方案数,即 。
可得:
注意到答案式中仅含
代码
const ll mod = 998244353;
const int N = 1000010, M = 1000000;
int t, n, k, a[N];
char c[N];
ll inv[N], fac[N], finv[N], ten[N], f[N], g[N], h1[N], h2[N];
inline ll C(ll n, ll m) {
if (m > n) return 0;
if (m == n || n == 0) return 1;
return fac[n] * finv[m] % mod * finv[n - m] % mod;
}
inline ll calc() {
ll res = ten[n] * f[n] % mod;
if (k == 1) return res;
for (int R = 1; R <= n - 1; R++)
res = (res + ten[R] * f[R] % mod * h1[n - R - 1] % mod) % mod;
for (int L = 2; L <= n; L++)
res = (res + ten[n] * ((f[n] + mod - f[L - 1]) % mod) % mod * h1[L - 2]) % mod;
if (k == 2) return res;
for (int len = 1; len <= n - 2; len++)
res = (res + h2[n - len - 2] * (((g[n - 1] + mod - g[len]) % mod + mod - ten[len] * g[n - 1 - len] % mod) % mod) % mod) % mod;
return res;
}
int main() {
fac[0] = fac[1] = 1;
for (int i = 2; i <= M; i++) fac[i] = fac[i - 1] * i % mod;
inv[1] = 1;
for (int i = 2; i <= M; i++) inv[i] = (mod - (mod / i) * inv[mod % i]) % mod;
finv[0] = finv[1] = 1;
for (int i = 2; i <= M; i++) finv[i] = finv[i - 1] * inv[i] % mod;
ten[0] = 1;
for (int i = 1; i <= M; i++) ten[i] = ten[i - 1] * 10 % mod;
t = read();
while (t--) {
k = read();
scanf("%s", c + 1);
n = strlen(c + 1);
for (int i = 1; i <= n; i++) a[i] = c[i] ^ 48;
for (int i = 1; i <= n; i++) h1[i] = h2[i] = 0;
ll iv10 = inv[10];
for (int i = 1; i <= n; i++) {
f[i] = (f[i - 1] + iv10 * a[i] % mod) % mod;
iv10 = iv10 * inv[10] % mod;
}
for (int i = 1; i <= n; i++) g[i] = (g[i - 1] + f[i] * ten[i] % mod) % mod;
h1[0] = h2[0] = 1;
if (k >= 2)
for (int i = 1; i <= n; i++) h1[i] = ((h1[i - 1] << 1) % mod + mod - C(i - 1, k - 2)) % mod;
if (k >= 3)
for (int i = 1; i <= n; i++) h2[i] = ((h2[i - 1] << 1) % mod + mod - C(i - 1, k - 3)) % mod;
printf("%lld\n", calc());
}
return 0;
}
参考资料
本文作者:shiranui
本文链接:https://www.cnblogs.com/shiranui/p/16854191.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步