ABC249E

f(i,j) 表示压缩后长度为 i,原串长度为 j 的方案数。

则最终答案就是 n1i=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;
}
posted @   Kobe303  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示