ABC249E
设 f(i,j) 表示压缩后长度为 i,原串长度为 j 的方案数。
则最终答案就是 ∑n−1i=1f(i,n)。
考虑转移,枚举下一段的长度 k,设长度的位数为 x,则有 f(i+1+x,j+k)←f(i+1+x,j+k)+25×f(i,j)。
初值 f(0,0)=2625,因为第一段连续的字母是可以随便选的。
考虑对于固定的 x,它对应的能更新到的是一段区间,能轻松用前缀和优化成 O(n2log10n)。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3005;
int n, p;
int pw[6] = {1, 10, 100, 1000, 10000 ,100000};
int f[N][N], sum[N][N];
int qpow(int x, int y) {
int res = 1;
while (y) {
if (y & 1) res = 1ll * res * x % p;
x = 1ll * x * x % p;
y >>= 1;
}
return res;
}
int main() {
scanf("%d%d", &n, &p);
f[0][0] = 1ll * qpow(25, p - 2) * 26 % p;
for (int i = 1; i <= n; ++i) sum[0][i] = f[0][0];
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
for (int k = 1; k <= 4; ++k) {
if (i - k - 1 < 0) break;
int x = max(0, j - pw[k - 1] + 1), y = max(0, j - pw[k] + 1);
f[i][j] += 1ll * (((sum[i - k - 1][x] - sum[i - k - 1][y]) % p + p) % p) * 25 % p;
f[i][j] %= p;
}
sum[i][j + 1] = (sum[i][j] + f[i][j]) % p;
}
}
int ans = 0;
for (int i = 1; i < n; ++i) ans = (ans + f[i][n]) % p;
printf("%d", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话