【贪心/Trie】【CF1083B】 The Fair Nut and Strings

Description

k 个长度为 n 的只含 ab 字符串,并不知道它们具体是多少,只知道它们的字典序不小于字符串 A,同时不大于字符串 B。定义一个字符串是合法的当且仅当它是这 k 个字符串之一的前缀(如果它是多个串的前缀那么只计算一次)。求合法的字符串最大可能是多少

Input

第一行是两个整数 nk

下面两行,第一行是长度为 n 的字符串 A,第二行是长度为 n 的字符串 B

Output

输出一个数代表答案。

Hint

1  n  5 × 105 , 1  k  109

Solution

我们考虑假如对这 k 个字符串建出一棵Trie树,那么显然一个节点对应一个合法的字符串,答案即为树上节点个数。于是我们的问题即被转化为了最大化Trie树上的节点个数。考虑在一个节点,在合法的条件下孩子数为 2 的答案显然不劣于孩子数为 1 的答案。于是我们依照此按照层数进行贪心,尽可能的多分节点即可。考虑因为最后一层的节点最多有 k 个,所以当算到一层的节点数不小于 k 时,后面就无需枚举,直接分配给每层 k 个节点计算答案即可。

Code

#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long

typedef long long int ll;

namespace IPT {
	const int L = 1000000;
	char buf[L], *front=buf, *end=buf;
	char GetChar() {
		if (front == end) {
			end = buf + fread(front = buf, 1, L, stdin);
			if (front == end) return -1;
		}
		return *(front++);
	}
}

template <typename T>
inline void qr(T &x) {
	rg char ch = IPT::GetChar(), lst = ' ';
	while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
	while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
	if (lst == '-') x = -x;
}

template <typename T>
inline void ReadDb(T &x) {
	rg char ch = IPT::GetChar(), lst = ' ';
	while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
	while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
	if (ch == '.') {
		ch = IPT::GetChar();
		double base = 1;
		while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
	}
	if (lst == '-') x = -x;
}

namespace OPT {
	char buf[120];
}

template <typename T>
inline void qw(T x, const char aft, const bool pt) {
	if (x < 0) {x = -x, putchar('-');}
	rg int top=0;
	do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
	while (top) putchar(OPT::buf[top--]);
	if (pt) putchar(aft);
}

const int maxn = 500010;

ll n, k, ans;
char MU[maxn], CU[maxn];

int main() {
	freopen("1.in", "r", stdin);
	qr(n); qr(k);
	do MU[1] = IPT::GetChar(); while ((MU[1] > 'z') || (MU[1] < 'a'));
	for (rg int i = 2; i <= n; ++i) MU[i] = IPT::GetChar();
	do CU[1] = IPT::GetChar(); while ((CU[1] > 'z') || (CU[1] < 'a'));
	for (rg int i = 2; i <= n; ++i) CU[i] = IPT::GetChar();
	ll pre = 1;
	for (rg int i = 1; i <= n; ++i) {
		pre <<= 1;
		if (MU[i] == 'b') --pre;
		if (CU[i] == 'a') --pre;
		if (pre >= k) {
			ans += 1ll * k * (n - i + 1);
			break;
		}
		ans += pre;
	}
	qw(ans, '\n', true);
	return 0;
}
posted @   一扶苏一  阅读(331)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示