[AGC058D] Yet Another ABC String 题解
非常棒的容斥题。
思路#
由于我们要求的是不存在子串 ABC
,BCA
和 CAB
的字符串。
我们可以对这个进行容斥。
如何容斥?
假如我们容斥有多少个不合法的子串,这样是非常不好计算的。
但是我们可以观察这道题的一些性质。
其实你从上一个容斥就可以看出,对于一个类似 ABCA
的串,它的长度只有
可以发现我们可以提出来一个极长的不合法子串。
这是由于他给的字符串的特殊性质。
那么就容易想到我们可以容斥它有多少个极长的不合法子串。
这个是比较好容斥的。
在容斥的时候,由于我们不需要关心他的长度,我们只需要限定他一定是一个不合法子串,并且是极长的即可。
那么可以通过钦定起点来计数。
首先假设有
那么我们其它的字符可以随意排列:
由于我们钦定的是起点,那么假如钦定的起点是
所以 A
后面可以接 ABC
和 CAB
。
B
后面可以接 ABC
和 BCA
。
C
后面可以接 BCA
和 CAB
。
每个点都是两种情况。
所以方案数可以用插板法算:
当然,这个答案还少了一种情况,我们的不合法串还可以在开头。
所以还有:
最后不要忘记容斥系数。
预处理组合数就可以了。
时间复杂度:
Code#
/*
! 如果没有天赋,那就一直重复
! Created: 2024/06/28 15:24:35
*/
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
// #define int long long
#define mp(x, y) make_pair(x, y)
#define eb(...) emplace_back(__VA_ARGS__)
#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)
inline void JYFILE19();
using i64 = long long;
using PII = pair<int, int>;
bool ST;
const int N = 3e6 + 10;
const int mod = 998244353;
int n, m, k, ans, all, f[N];
namespace Math {
const int I = N; i64 fac[I], inv[I], pw2[I];
template<typename T> inline void add(T &x, i64 y) { x = (x + y >= mod ? x + y - mod : x + y); }
template<typename T> inline void mul(T &x, i64 y) { x = (x * y >= mod ? x * y % mod : x * y); }
inline i64 Add(i64 x, i64 y) { return (x + y >= mod ? x + y - mod : x + y); }
inline i64 Mul(i64 x, i64 y) { return (x * y >= mod ? x * y % mod : x * y); }
inline i64 power(i64 x, i64 y) {
i64 res = 1; while(y) {
if(y & 1) res = res * x % mod;
x = x * x % mod, y /= 2;
}
return res;
}
inline void init(int n = I - 10) {
fac[0] = pw2[0] = 1;
fro(i, 1, n) fac[i] = Mul(fac[i - 1], i);
fro(i, 1, n) pw2[i] = pw2[i - 1] * 2 % mod;
inv[n] = power(fac[n], mod - 2);
pre(i, n, 1) inv[i - 1] = Mul(inv[i], i);
}
inline i64 C(i64 x, i64 y) {
if (x < 0 || y < 0 || x - y < 0) return 0;
return Mul(fac[x], Mul(inv[y], inv[x - y]));
}
} using namespace Math;
inline i64 C(i64 a, i64 b, i64 c) {
return fac[a + b + c] * inv[a] % mod * inv[b] % mod * inv[c] % mod;
}
signed main() {
JYFILE19();
cin >> n >> m >> k, init(all = n + m + k);
fro(i, 0, min({n, m, k})) {
i64 res = C(n - i, m - i, k - i);
if (i) {
int x = Mul(C(all - i - i - 1, all - i - i - i - 1), pw2[i]);
int y = Mul(C(all - i - i - 1, all - i - i - i), pw2[i - 1]) * 3 % mod;
res = res * (x + y) % mod;
}
add(ans, (i & 1 ? mod - res : res));
}
cout << ans << "\n";
return 0;
}
bool ED;
inline void JYFILE19() {
// freopen("", "r", stdin);
// freopen("", "w", stdout);
srand(random_device{}());
ios::sync_with_stdio(0), cin.tie(0);
double MIB = fabs((&ED - &ST) / 1048576.), LIM = 1024;
cerr << "MEMORY: " << MIB << endl, assert(MIB <= LIM);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)