CF946E

为了让我们构造出来的结果尽量大而又不超过给定的 s,当我们构造的串长度跟 s 相同时,就可以知道存在一个 k 满足我们构造出来的串前 k1 位和 s 一样,第 k 位比 sk 小,然后后面 k+1n 位能使串满足定义又尽量大。

所以我们从高位到低位枚举那个被修改小的位置 k,然后从大到小枚举它被改成的数字。接下来如何判断成立与否了,因为前 k1 位我们填的都是 s 串中对应的数,第 k 位又是我们枚举出来的,而我们又要满足所有数字出现次数为偶数次,所以前 k 位出现次数为奇数的数字都得在后面出现奇数次。所以,如果出现为奇数次的数字数量 x 大于 nk,则无法构造出来,否则可以。

至于构造方法,就是最后 x 位从大到小填上那些需要补全为偶数次的数字,中间剩余的位置都填 9 即可。

统计一段前缀每种数字出现的奇偶次数可以预处理出来,所以总复杂度是线性的。

若找不到满足条件的等长串,则输出 n29

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