CF946E
为了让我们构造出来的结果尽量大而又不超过给定的 s,当我们构造的串长度跟 s 相同时,就可以知道存在一个 k 满足我们构造出来的串前 k−1 位和 s 一样,第 k 位比 sk 小,然后后面 k+1 到 n 位能使串满足定义又尽量大。
所以我们从高位到低位枚举那个被修改小的位置 k,然后从大到小枚举它被改成的数字。接下来如何判断成立与否了,因为前 k−1 位我们填的都是 s 串中对应的数,第 k 位又是我们枚举出来的,而我们又要满足所有数字出现次数为偶数次,所以前 k 位出现次数为奇数的数字都得在后面出现奇数次。所以,如果出现为奇数次的数字数量 x 大于 n−k,则无法构造出来,否则可以。
至于构造方法,就是最后 x 位从大到小填上那些需要补全为偶数次的数字,中间剩余的位置都填 9 即可。
统计一段前缀每种数字出现的奇偶次数可以预处理出来,所以总复杂度是线性的。
若找不到满足条件的等长串,则输出 n−2 个 9。
Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int T;
int n, m;
int sum[N][10];
char s[N];
void solve() {
scanf("%s", s + 1), n = strlen(s + 1);
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < 10; ++j)
sum[i][j] = sum[i - 1][j] ^ (s[i] - '0' == j);
}
for (int i = n; i; --i)
for (int j = s[i] - '0' - 1; ~j; --j) {
if (i == 1 && j == 0) continue;
int tmp = 0;
for (int k = 0; k < 10; ++k) tmp += sum[i - 1][k] ^ (j == k);
if (tmp <= n - i) {
for (int k = 1; k < i; ++k) putchar(s[k]);
putchar(j + '0');
for (int k = i + 1; k <= n - tmp; ++k) putchar('9');
for (int k = 9; ~k; --k)
if (sum[i - 1][k] ^ (j == k)) putchar(k + '0');
printf("\n"); return;
}
}
for (int i = 1; i <= n - 2; ++i) putchar('9');
printf("\n");
}
int main() {
scanf("%d", &T);
while (T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话