闲话 23.3.27
闲话
某人写了 INTERNET YAMERO 上黑板
……我觉得会被跳过
另一个人写了 Brain Power 上黑板
A 老师:这玩意有词?
美式咖啡喝凉的好还是热的好?
你说得对,但是我喝摩卡和拿铁
模拟赛
这模拟赛打的 明天是要模拟如何翻盘?
T1
签到题。考虑直接枚举前面的 BABA...BA
是 ,这样的 可以枚举 BA
长度后 check 段得到。然后就是统计 段和 BA
的 lcp 长度,可以二分得到。
通过哈希实现的总时间复杂度 ,注意数组是否越界。
T2
考场降智时刻。
考虑第一问。设 表示子树内叶子情况全知道的最小花费, 表示有且只有一个叶子不知道的最小花费,转移就是 。叶子初值 。
考虑第三问。设 表示子树内叶子情况全知道的所有情况, 表示有且只有一个叶子不知道的所有情况,我们只需要按上面的最小情况转移即可。也就是说,上面加法改成乘法,上面最小值改成把所有最小情况加和即可。叶子初值 。
考虑第二问。我们按照上面的情况直接再做一遍递归即可。也就是说,我们按照最优方案 dfs,dfs 时记录当前节点子树内还有几个叶子不知道,再记忆化,保证只搜索 次。
总时间复杂度 。
T3
设 表示到 点,还剩 点生命值时答案的期望。不难写出
我们发现,这是有后效性的,但是所有后效性只取决于 这一个点的值。考虑如何把这个点的值删去。
引入变元 ,我们设 为如上的期望对变元的函数。可以证明的是,。
证明考虑归纳法。
我们首先观察 ,这些函数总是定值 ,因此 。
我们已经知道了对 全满足这条件,现在需要证明 也满足这条件。可以简记形态为
其中 。它的曲线非光滑,但由于间断点都是第一类的,我们可以只对连续的部分考虑导数,最后讨论间断点。也就是说我们只需要对 的前后两部分分别归纳证明。前一部分是显然的,\dfrac{\text d}{\text dx} (x + c) = 1 \le 1$,而后一部分可以知道
由于是取 操作,因此图像连续。由于函数在光滑部分的导数 ,并由 操作的性质,任意两个间断点总是由导数大的函数切换至导数小的函数。所以 的导数小于等于 的两个参数的。
这也就证明了 也满足这条件。
考虑这是个 dag,点 的出边只会指向 的点。因此假设我们已知了 段都符合要求,总存在一个只连向 段的节点使得我们可以拓展符合要求的区间,取 即可。
证毕。
所以我们也能知道 ,即 。这也就说明了 是有单调性的。我们只需要二分得到 的 ,这 就是答案。
总时间复杂度 ,其中 是答案的值域。
杂题
给定 和 ,请问能构造满足以下条件的数组对 中, 长度之和是多少:
- 数组长度相等且长度大于 ,设数组长度都为 。
- ,,。
- 每个数组都单调不下降且对于所有 都满足 。
答案对 取模。
。
好像有高妙格路计数,不是很懂。
考虑数组单调不降,所以 ,等号当且仅当 。所以 3. 条件说的很明白了:两个数组不升的位置不能有重合。
这启发我们枚举不升的位置计数。我们枚举长度是 , 序列升的位置分别为 个。首先有 的贡献,并且分配 的值给 个升的位置等价于 个球放在 个有标号盒子里且不能有空盒子,方案数就是 。最后是分配不升的位置,首先分配 序列的方案数是 个,而 序列可以考虑 个不升的位置必须要和 个 中升的位置重合,方案数是 。所以有答案就是
接下来我们要解决的是 的计算。我们不妨考虑更广泛的情况,即已知一个 次多项式 的系数,计算 。
由于这题 较小,我们可以考虑直接计算每个 。你定睛一看——这不是《载谭 Binomial Sum》吗?所以可以做到 O(k + log n)
由于这题 ,我们可以直接考虑计算每个 。
时是经典结论 。
时可以知道答案就是
时可以拆成下降幂形式,自然得到。
所以我们可以 解决原问题。
如果一个字符串可以被拆分为 的形式,其中 和 是任意非空字符串,则我们称该字符串的这种拆分是优秀的。现在给出一个长度为 的字符串 ,我们需要求出,在它所有子串的所有拆分方式中,优秀拆分的总个数。这里的子串是指字符串中连续的一段。
。
好久之前就想学这个套路了但是一直没写(
假设从 点开始的形如 AA
的串数是 ,从 点结束的形如 AA
的串数是 ,则 就是答案。考虑如何计算这两个值。
考虑枚举长度 ,我们每次统计长度为 的串会对哪些点的 产生贡献。
我们在 的位置撒关键点,这样每个形如 AA
的串都会经过且仅经过相邻的 2 个点。由于总点数是 的,我们可以枚举相邻点算贡献。假设当前的两个点是 和 。
假设我们求出了前缀 和 的最长公共后缀 ,以及后缀 和 的最长公共前缀 。
考虑当 时不可能有解,我们总能取 中一个字符作为两个串中不等的字符的例子。
而当 时,我们总能从 位置开始向后取一段,这一段内都可以作为 AA
串的起点,直到最右侧达到 。终点类似。
这样我们就可以对 做区间加了。由于我们是先加再求,考虑差分维护即可。最长公共前后缀可以采用 SA + st表的方式求解。
总时间复杂度 。
类似题:UVA10829。
code
#include <bits/stdc++.h>
using namespace std;
using pii = pair<int,int>; using vi = vector<int>; using vp = vector<pii>; using ll = long long;
using ull = unsigned long long; using db = double; using ld = long double; using lll = __int128_t;
template<typename T1, typename T2> T1 max(T1 a, T2 b) { return a > b ? a : b; }
template<typename T1, typename T2> T1 min(T1 a, T2 b) { return a < b ? a : b; }
#define multi int _T_; cin >> _T_; for (int TestNo = 1; TestNo <= _T_; ++ TestNo)
#define timer cerr << 1. * clock() / CLOCKS_PER_SEC << '\n';
#define iot ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i,s,t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
#define eb emplace_back
#define pb pop_back
const int N = 30000 + 10;
const int inf = 0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fll;
int n, a[N], b[N];
template <typename _Tp = char, const int siz = 127>
struct SA {
_Tp ch[N];
int n = -1, sa[N], rk[N], heg[N];
int a[N], tr[siz + 5], cur[N];
int sum[N], bse[N << 3], *_t = bse;
_Tp* begin() { return ch + 1; }
const _Tp operator [] (const int & p) const { return ch[p]; }
_Tp & operator [] (const int & p) { return ch[p]; }
#define _MemAlloc(pool, size, tag) (tag = pool, pool += size)
#define pushs(x) (sa[cur[a[x]] --] = x)
#define pushi(x) (sa[cur[a[x]] ++] = x)
#define inds(lms) \
rep(i,1,n) sa[i] = -1, sum[i] = 0; \
rep(i,1,n) sum[a[i]] ++; \
rep(i,1,n) sum[i] += sum[i - 1]; \
rep(i,1,n) cur[i] = sum[i]; \
pre(i,m,1) pushs(lms[i]); \
rep(i,1,n) cur[i] = sum[i - 1] + 1; \
rep(i,1,n) if (sa[i] > 1 and !tp[sa[i] - 1]) pushi(sa[i] - 1); \
rep(i,1,n) cur[i] = sum[i]; \
pre(i,n,1) if (sa[i] > 1 and tp[sa[i] - 1]) pushs(sa[i] - 1);
inline void SA_IS(int n, int* a) {
int* tp; _MemAlloc(_t, n + 1, tp); tp[n] = 1;
int* p; _MemAlloc(_t, n + 2, p);
pre(i,n-1,1) tp[i] = (a[i] == a[i + 1]) ? tp[i + 1] : (a[i] < a[i + 1]);
int m = 0, tot = 0;
rep(i,1,n) rk[i] = (tp[i] and !tp[i - 1]) ? (p[++ m] = i, m) : -1;
inds(p);
int* a1; _MemAlloc(_t, m + 1, a1);
p[m + 1] = n;
for (int i = 1, x, y; i <= n; ++ i) if ((x = rk[sa[i]]) != -1) {
if (tot == 0 or p[x + 1] - p[x] != p[y + 1] - p[y]) ++ tot;
else for (int p1 = p[x], p2 = p[y]; p2 <= p[y + 1]; ++ p1, ++ p2)
if ((a[p1] << 1 | tp[p1]) != (a[p2] << 1 | tp[p2])) { ++ tot; break; }
a1[y = x] = tot;
}
if (tot == m) rep(i,1,m) sa[a1[i]] = i;
else SA_IS(m, a1);
rep(i,1,m) a1[i] = p[sa[i]];
inds(a1);
}
int st[N][20], lgv[N];
void build() {
n = strlen(begin());
memset(tr, 0, sizeof tr);
rep(i,1,n) tr[ch[i]] = 1;
rep(i,1,siz + 1) tr[i] += tr[i - 1];
rep(i,1,n) a[i] = tr[ch[i]] + 1;
a[n + 1] = 1; _t = bse;
SA_IS(n + 1, a);
rep(i,1,n) sa[i] = sa[i + 1];
rep(i,1,n) rk[sa[i]] = i;
for (int i = 1, k = 0; i <= n; ++ i) {
if (rk[i] == 0) continue;
if (k) -- k;
while (ch[i + k] == ch[sa[rk[i] - 1] + k]) ++ k;
heg[rk[i]] = k;
}
rep(i,1,n) st[i][0] = heg[i];
rep(i,2,n) lgv[i] = lgv[i >> 1] + 1;
rep(i,1,lgv[n]) for (int j = 1; j + (1 << i) - 1 <= n; ++ j)
st[j][i] = min(st[j][i - 1], st[j + (1 << i - 1)][i - 1]);
}
int lcp(int l, int r) {
if (l <= 0 or l > n or r <= 0 or r > n) return 0;
l = rk[l], r = rk[r];
if(l > r) swap(l, r); l++;
int k = lgv[r - l + 1];
return min(st[l][k], st[r - (1 << k) + 1][k]);
}
}; SA<> sa[2];
signed main() {
multi {
cin >> sa[0].begin();
sa[0].build(); n = sa[0].n;
rep(i,1,n) sa[1][i] = sa[0][n - i + 1]; sa[1][n + 1] = 0;
sa[1].build();
rep(i,1,n) a[i] = b[i] = 0;
for (int len = 1; len <= n / 2; ++ len) {
for (int i = len; i <= n; i += len) {
int l1 = i, r1 = i + len, l2 = n - (r1 - 1) + 1, r2 = n - (l1 - 1) + 1;
int lcp = min(len, sa[0].lcp(l1, r1));
int lcs = min(len - 1, sa[1].lcp(l2, r2));
if (lcp + lcs >= len) {
b[i - lcs] ++, b[i - lcs + (lcp + lcs - len + 1)] --;
a[r1 + lcp - (lcp + lcs - len + 1)] ++, a[r1 + lcp] --;
}
}
} rep(i,1,n) a[i] += a[i - 1], b[i] += b[i - 1];
ll ans = 0;
rep(i,1,n - 1) ans += 1ll * a[i] * b[i + 1];
cout << ans << '\n';
}
}
以下是博客签名,与正文无关。
请按如下方式引用此页:
本文作者 joke3579,原文链接:https://www.cnblogs.com/joke3579/p/chitchat230327.html。
遵循 CC BY-NC-SA 4.0 协议。
请读者尽量不要在评论区发布与博客内文完全无关的评论,视情况可能删除。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义