日记

杜绝摸鱼。

已经成垃圾桶了。

2025/08/23

练习 SOS / 高维前缀和。VJ.

2025/08/25

继续做 SOS。

CF1620G Subsequences Galore

现有全集 \(U=\{1,\dots,n\}\),对于每个集合 \(S\subseteq U\) 能够以 \(O(n)\) 算出 \(g(S)=\left|\bigcap\limits_{x\in S}A_x\right|\)。求 \(f(S)=\left|\bigcup\limits_{x\in S}A_x\right|\).


容斥得到

\[\begin{aligned} f(S)&=\left|\bigcup\limits_{x\in S}A_x\right|\\ &=\sum_{T\subseteq S}(-1)^{|T|+1}\left|\bigcap\limits_{x\in T}A_x\right|\\ &=\sum_{T\subseteq S}(-1)^{|T|+1}g(T)\\ \end{aligned} \]

这个可以高维前缀和搞定。复杂度 \(O(n2^n)\)

P9333 [JOIST 2023] 议会 / Council

\(i\) 通过的决议集合为 \(A_i\)。对于主席 \(i\),可以统计其余人各决议的票数,\(>\lfloor\frac n2\rfloor\) 的必定通过,\(<\lfloor\frac n2\rfloor\) 的必定不通过,所以只用考虑 \(=\lfloor\frac n2\rfloor\) 的决议集合 \(S\)

现在只用求 \(\max\limits_{j\ne i}\operatorname{popcount}(S\bigcap\overline{A_j})\)

由于带 \(\operatorname{popcount}\),不好直接前缀和。在 \(S\bigcap\overline{A_j}\) 的角度计算贡献,对于 \(A\) 先做一遍后缀和,再将每个点的权值赋成 \(\operatorname{popcount}\),前缀和,即为答案。要记录最大 / 次大值及其下标。

2025/08/28

模拟赛。只会 T1

T2

给定质数 \(P\)\(q\) 次询问,每次给定 \(n,m\),求有多少个长为 \(n\),元素 \(\in[0,m]\bigcap Z\) 的序列 \(a\),满足 \(\nexists i<j<k\) 满足 \(a_k<a_i<a_j\)。答案对 \(P\) 取模。


我们不关注序列具体值,只关注相对大小。所以状态中可以只记录出现值的种类数。令 \(f_{i,j}\) 表示前 \(i\) 个数共出现了 \(j\) 种值。

转移时枚举第一个最大值的位置 \(k\) 以及前 \(k-1\) 个位置出现了 \(l\) 种值。由于此时 \(a_1,a_2,\cdots,a_{k-1}<a_k\),后面的值必须大于等于 \(\max\{a_1,a_2,\cdots a_{k-1}\}\),即这 \(l\) 种值是最小的 \(l\) 种:\(1,2,\cdots,l\)。所以后面 \(i-k\) 个位置包含了 \((l),l+1,\cdots,(j)\)\(4\) 种情况加和即可。

f[1][1] = 1;
for(re int i = 2; i < maxn; ++i) for(re int j = 1; j <= i; ++j)
{
	f[i][j] = (f[i - 1][j - 1]/*k=i*/ + f[i - 1][j] + f[i - 1][j - 1]) % mod;//k=1<i
	for(re int k = 2; k < i; ++k) for(re int l = 1; l < k && l < j; ++l)
	{
		f[i][j] += f[k - 1][l] * f[i - k][j - l + 1];//l,...,j
		f[i][j] += 2 * f[k - 1][l] * f[i - k][j - l];//l,...,j-1 / l+1,...,j
		/*if(l + 1 < j) */f[i][j] += f[k - 1][l] * f[i - k][j - l - 1];//l+1,...,j-1
		f[i][j] %= mod;
	}
}

2025/10/18

CF436E Cardboard Box

考虑反悔贪心。由于费用关于星星数是上凸的,每次新加一颗星,只需要考虑当前的最小费用。又有上一轮的最小费用已经确定,故本轮不可能有多次反悔,最多反悔一次,即 +2-1 型或 +1 型。分讨取最小 / 次小即可。

注意可以一次通关一个 \(2\) 星关卡并返回掉一个 \(1\) 星关卡。

int n, w, a[maxn], b[maxn], val[maxn];
ll ans;
set<pair<int, int> > ins, del, wait;
pair<int, int> getdel(int pos) {return {val[pos] == 2? a[pos] - b[pos]: -a[pos], pos};}
pair<int, int> getadd(int pos) {return {val[pos] == 0? a[pos]: (b[pos] - a[pos]), pos};}
void update(int pos, int delta)
{
	if(val[pos] < 2) ins.erase(getadd(pos));
	if(val[pos]) del.erase(getdel(pos));
	else wait.erase({b[pos], pos});
	val[pos] += delta;
	if(val[pos] < 2) ins.insert(getadd(pos));
	if(val[pos]) del.insert(getdel(pos));
	else wait.insert({b[pos], pos});
	// printf("add %d,%d\n", pos, delta);
}
int main()
{
	// input...
	// solve
	for(int i = 1; i <= n; i++) ins.insert({a[i], i}), wait.insert({b[i], i});
	while(w--)
	{
		ll val1;
		int pos1, pos2 = -1, pos3;
		//case 1:+min
		val1 = ins.begin()->first;
		pos1 = ins.begin()->second;
		if(ins.size() > 1)
		{
			if(val[pos1]) del.erase(getdel(pos1));
			auto it = next(ins.begin());
			if(del.size() > (val[it->second] > 0))
			{
				if(val[it->second]) del.erase(getdel(it->second));
				ll tmp = getadd(pos1).first + it->first + del.begin()->first;
				if(tmp < val1) val1 = tmp, pos2 = del.begin()->second, pos3 = it->second;
				if(val[it->second]) del.insert(getdel(it->second));
			}
			if(del.size() && ins.size() - 1 > (val[del.begin()->second] < 2))
			{
				if(val[del.begin()->second] < 2) ins.erase(getadd(del.begin()->second));
				ll tmp = getadd(pos1).first + del.begin()->first + next(ins.begin())->first;
				if(tmp < val1) val1 = tmp, pos2 = del.begin()->second, pos3 = next(ins.begin())->second;
				if(val[del.begin()->second] < 2) ins.insert(getadd(del.begin()->second));
			}
			if(val[pos1]) del.insert(getdel(pos1));
		}
		//case 2:-min
		if(val[pos1])
		{
			int now = pos1;
			ins.erase(getadd(now));
			if(ins.size() >= 2)
			{
				ll tmp = getdel(now).first + ins.begin()->first + next(ins.begin())->first;
				if(tmp < val1) val1 = tmp, pos1 = ins.begin()->second, pos2 = now, pos3 = next(ins.begin())->second;
			}
			ins.insert(getadd(now));
		}
		//case 3:0->2 & -1
		if(wait.size() && del.size() && wait.begin()->first + del.begin()->first < val1)
		{
			val1 = wait.begin()->first + del.begin()->first;
			pos1 = pos3 = wait.begin()->second, pos2 = del.begin()->second;
		}
		ans += val1;
		update(pos1, 1);
		if(!~pos2) continue;
		update(pos2, -1);
		update(pos3, 1);
	}

2026/03/31

ARC098D Donation

对于每个点,只有在最后一次经过它时捐款才最优。

若将整个过程倒序,则限制为每次经过点 \(i\) 时,至少得有 \(C_i=\max(0,A_i-B_i)\) 元。

按每条边的 \(\max(C_u,C_v)\) 从小到大排序,建立 Kruscal 重构树。

最终策略必为:从一个叶子出发,逐层向上,每走到一个点,就将其未被访问的儿子的子树全部吃下。

\(f_i\):起点在 \(\text{sub}(i)\) 内,吃下整个子树的最小初始金额,\(s_i\) 表示子树内能收获的总金额。

转移:\(f_x=\min_{y\in\text{sub}(i)}\max(f_y,C_x-s_y)\).

2026/04/11

ARC217B Not High Element

AI 题解(笑)。

首先看到这个 \(f(P)\),思考怎么将它量化地表示。

\(c_x\) 表示 \(x\) 这个 在最优决策中操作了几次。

我们发现,\(y\) 操作后,若 \(x<y\),则 \(x\) 也可以被带着操作一次。而且如果 \(y\) 需要带动的有一堆数,那我们可以从大往小操作。

所以有 \(c_x=I_x+\sum_{y=x+1}^nc_y\)\(I_x\) 表示初始时 \(x\) 能不能操作,即 \([x~不是前缀最大值]\))。

因此 \(\sum_{x=1}^nc_x=\sum_{x=1}^nI_x2^{x-1}\)。当然,这个不是很好算,毕竟“不是前缀最大值”这个限制比较奇怪。

所以换成总的减去是前缀最大值的贡献即可。

对于每个比已给出的数都大的数 \(x\),它的贡献就是 \(-2^{x-1}(n-k)!\frac{(n-x)!}{(n-x+1)!}=-2^{x-1}(n-k)!\frac1{n-x+1}\).

ARC217C Greedy Customers 2

又是 AI 题解。

将能买的最贵的物品相同的人一并考虑。设钱数落在 \([a_i,a_{i+1})\) 的概率为 \(p_i\)

若已经确定了第 \(i\) 种人有 \(c_i\) 个,则这种情况的出现概率为 \(\frac{n!}{\prod_{i=0}^nc_i!}\prod_{i=0}^np_i^{c_i}\)

由于高种类的人可以买低种类的物品,所以从高到低 DP,设 \(f_{i,j,k}\) 表示考虑前 \(i\) 高的种类,共 \(j\) 人,有 \(k\) 人空闲的概率。

显然有转移 \(f_{i,j,k}\to f_{i-1,j+c,\max(0,k+c-1)}\)(当然,还要将上面的出现概率部分乘进来)。

最后对于所有 \(f_{1,i,j}\),共卖出 \(i-j\) 个物品。

2026/05/09

CF1861E Non-Intersecting Subpermutations

容易想到设 \(f_{i,j}\) 表示前 \(i\) 位,末尾最长 \(j\) 位不同。但是发现会算重。

那就对于 \(j=K\) 的,直接强制让下一位时的最长后缀变成 \(1\)

然后前缀和优化,然后没了。Submission.

2026/05/12

CF1801D The way home

有很聪明的状态:\(f_{i,j}\) 表示到 \(i\),当前经过的最大 \(w\) 的点为 \(j\),此时最小的表演次数与最大的剩余金额。又发现中间的非前缀最大 \(w\)\(i\) 贡献长得差不多,就变成 \(f_i\):当前在 \(i\)\(w_i\) 为当前的最大 \(w\)

观察到有两个东西同时取最优,这个不好整。但是在确定位置与经过的最大 \(w\) 的情况下,一定优先最小化表演次数,再最大化剩余金额(表演肯定越靠后越优,就算表演次数多的那种方案剩余金额大,也不如表演次数少的在补全差的次数之后剩余的金额大)。

转移需要任意两点间最短路,故需要预处理全源最短路。\(O(nm\log n+n^2)\)

Submission.

2026/05/13

P9017 [USACO23JAN] Lights Off G

读题乃一大难点:一次操作中 \(3\)都要执行

答案明显在 \(3n\) 以内(题解说在 \(n\) 以内,呃呃),所以枚举答案。发现已知答案 \(ans\) 后初始给定 \(b\) 的影响可以模拟一遍后消去,只考虑翻转带来的影响:\(ans\) 个长度为 \(1\sim ans\)环上 区间会被整体翻转。这个可以用状压求所有可能的翻转方案。Submission.

P9016 [USACO23JAN] Find and Replace G

发现修改呈递归式的树形结构,所以从后往前(即从递归树的儿子向父亲)构建这颗树。建完树后二分即可。

要特判 \(\operatorname{len}(s_i)=1\) 的情况!否则会出现大量的链被重复访问,复杂度就不是 \(O(n+r-l+1)\) 了。Submission.

ARC156D Xor Sum 5

牛牛牛。

答案为 \(\bigoplus\limits_{[x^S](\sum_{i=1}^nx^{a_i})^k\equiv1\pmod2}S\)。考虑化简 \(S\) 满足的条件。

\(k=\sum_{i=1}^m2^{p_i}\)。因为 \([x^S](\sum_{i=1}^nx^{a_i})^2\equiv[x^S]\sum_{i=1}^nx^{2a_i}\),故有:

\[\large \begin{aligned} \left[x^S\right](\sum_{i=1}^nx^{a_i})^k&=[x^S]\prod_{i=1}^m(\sum_{j=1}^nx^{a_j})^{2^{p_i}}\\ &\equiv[x^S]\prod_{i=1}^m\sum_{j=1}^nx^{a_j\cdot2^{p_i}}\\ \end{aligned} \]

组合意义即为“有 \(m\) 轮选数,第 \(i\) 轮选一个 \(a\cdot2^{p_i}\),要求加和为 \(S\)”。

我们枚举每一位 \(i\),将所有 \(p_j\leqslant i\) 都纳入考虑,则对于后面的位置,这 \(i+1\) 位是什么并不重要,所以每次更新后的 \(S\)\(i+1\) 的贡献可以直接转移给 \(\lfloor\frac S2\rfloor\)。细节见代码。

int n, a[1005];
ll k, ans;
bitset<2005> A, f, g;
int main()
{
	read(n, k);
	for(int i = 1; i <= n; i++) read(a[i]), A.flip(a[i]);
	f.flip(0);
	for(int i = 0; i < 50; i++)
	{
		if(k & 1)
		{
			g.reset();
			for(int j = 0; j <= 2000; j++)
				if(f[j]) g ^= A << j;
			f = g;
		}
		k >>= 1;
		int c = 0;
		for(int j = 1; j <= 2000; j += 2) c ^= f[j];
		// c*n^popcount(k) mod 2 = 1
		if(c && ((n & 1) || !k)) ans |= 1ll << i;
		g.reset();
		for(int j = 0; j <= 2000; j++)
			if(f[j]) g.flip(j >> 1);
		f = g;
	}
	printf("%lld\n", ans);
	return 0;
}

2026/05/21

CF2004F Make a Palindrome

可以发现分裂、合并只取其一即可,这里只保留合并操作。证明则考虑分裂时裂出来的两元素对应元素合并是一个效果。

那么对于固定的 \([l,r]\),其 \(f(l,r)\) 为区间长减去从两头起最多能划分出的和对应相等的段数。后者也就是区间中有多少组前后缀和相等。(可以均为该区间本身)

所以任意一组和相等的区间能唯一确定一个对应的 \([l,r]\),总共要减去的就是任选两(可能相同)区间且和相等的方案数。

Submission.

2026/05/23

P16330 Just Because!

神仙。

发现暴力的 DP 没法优化,考虑转成数轴上选线段问题,每次所选线段不交。但这样会把“左边往右倒、右边往左倒”的情况漏掉。所以还要单独把这种合成的权值为 \(2\) 的区间补上。

现在每个区间的权值是 \(1\) 或者 \(2\),没法直接倍增。回到问题中的隐式图上,考虑记录当前答案对应的最小坐标 以及答案减一对应的最小坐标,这样就不会把走权值为 \(2\) 的路径漏掉。

此时倍增所需的 \(2^k\) 步长就可以用 \(2^{k-1}+2^{k-1}\)\((2^{k-1}-1)+2+(2^{k-1}-1)\) 来凑,相较普通倍增多记录一个 \(2^k-1\) 步走到的位置即可。

Submission.

2026/05/27

APIO 2026 中国赛区 T3 集宝

首先有蠢猪暴力:每次从当前所在位置跳到最近的能收集下一颗宝石的位置。跳一次只需要求 LCA 及树上 k 级祖先,\(O(\log n)\) 实现的话就有 \(O(n\log n)-O(qm\log n)\)

然后考虑怎么加速区间查:能否将两个连续的(不妨设为相交,相离时就直接化简成两圆心连线上的一部分链)圆化简?——直接用二者的交替换即可。

又有神秘性质:树上的“圆”的交还是一个“圆”的形式。如此维护即可。但是难写。Submission.

2026/05/29

有标号 DAG 计数

弱联通的限制太紧,设弱联通的 EGF 为 \(F(x)\),不要求联通的 EGF 为 \(G(x)\),则 \(G(x)=e^{F(x)}\),即 \(F(x)=\ln G(x)\)

现在不必弱联通,设 \(f_i\)\(i\) 点 DAG 数,则 \(f_i=\sum_{j=1}^i a_j\),其中 \(a_j=\binom ij f_{i-j}2^{j(i-j)}\) 为刚好有 \(j\)\(0\) 度点的方案。

\(b_j=\sum_{k\geqslant j}\binom kj a_k\) 表示至少有 \(i\)\(0\) 度点的方案,二项式反演得 \(a_j=\sum_{k\geqslant j}\binom kj b_k(-1)^{k-j}\)

结合 结论 \(ab=\binom{a+b}2-\binom a2-\binom b2\),代入转移即得 \(f_n=n!2^{\binom n2}\sum_{i=1}^n\frac{(-1)^{i+1}}{i!2^{\binom i2}}\cdot\frac{f_{n-i}}{(n-i)!2^{\binom{n-i}2}}\)

另设 \(g_n=\frac{f_n}{n!2^{\binom n2}}=\sum_{i=1}^n\frac{(-1)^{i+1}}{i!2^{\binom i2}}\cdot g_{n-i}\),移项得 \(\sum_{i=0}^n\frac{(-1)^i}{i!2^{\binom i2}}g_{n-i}=[n=0]\)

\(\{g_n\}\) 生成函数为 \(\{\frac{(-1)^n}{n!2^{\binom n2}}\}\) 生成函数的乘法逆。还原即可得到 \(G(x)\),进而求得 \(F(x)\)

Submission.

2026/06/03

CF932E Team Work

\[\begin{aligned} \sum_{i=1}^n\binom nii^k &=\sum_{i=1}^n\binom ni\sum_{j=1}^i\binom ij{k\brace j}j!\\ &=\sum_{i=1}^n\frac{n!}{i!(n-i)!}\sum_{j=1}^i\frac{i!}{j!(i-j)!}{k\brace j}j!\\ &=n!\sum_{i=1}^n\frac1{(n-i)!}\sum_{j=1}^i\frac{k\brace j}{(i-j)!}\\ \end{aligned} \]

\(F(x)=\sum_{i=0}^{\infty}\frac{x^i}{i!}=e^x\)\(G(x)=\sum_{i=1}^k{k\brace i}x^i\),则所求即为:

\[\begin{aligned} n![x^n]\left(F^2(x)G(x)\right) &=[x^0]\left(G(x)e^{2x}\right)^{(n)}\\ &=\sum_{i=0}^n\binom ni[x^0]\left(G^{(i)}(x)2^{n-i}e^{2x}\right)\\ &=\sum_{i=0}^n\binom nii!{k\brace i}2^{n-i}\\ &=\sum_{i=0}^nn^{\underline i}{k\brace i}2^{n-i}\\ \end{aligned} \]

其中 \(f^{(n)}(x)\) 表示 \(f(x)\)\(n\) 阶导数,由莱布尼茨公式:\(\left(f(x)g(x)\right)^{(n)}=\sum_{i=0}^n\binom nif^{(i)}(x)g^{(n-i)}(x)\)

\(O(k^2)\) 预处理 \(k\brace i\)\(O(k)\) 枚举求和即可。Submission.

2026/06/04

[集训队互测 2011] Crash 的文明世界

\[\begin{aligned} \sum_{i=1}^nd_i^k &=\sum_{i=1}^n\sum_{j=1}^k\binom{d_i}j{k\brace j}j!\\ &=\sum_{i=1}^k{k\brace i}i!\sum_{j=1}^n\binom{d_j}i\\ \end{aligned} \]

问题变为对每个点求以它为根时,\(\forall1\leqslant j\leqslant k\)\(\sum_{i=1}^n\binom{d_i}j\)。观察到 \(\binom{d_i}j=\binom{d_i-1}j+\binom{d_i}{j-1}\),所以相邻节点的和可以相互转移。稍有细节。Submission.

CF961G Partitions

对于每个 \(w_i\),它乘的系数都是一定的,为所有情况中包含该元素的集合大小之和,即:

\[\begin{aligned} \sum_{i=1}^n\binom{n-1}{i-1}i{n-i\brace k-1} &=\sum_{i=1}^n\binom{n-1}{i-1}i\frac1{(k-1)!}\sum_{j=0}^{k-1}\binom{k-1}j(-1)^{k-1-j}j^{n-i}\\ &=\sum_{j=0}^{k-1}\frac1{j!(k-1-j)!}(-1)^{k-1-j}\sum_{i=1}^n\binom{n-1}{i-1}ij^{n-i}\\ &=\sum_{j=0}^{k-1}\frac1{j!(k-1-j)!}(-1)^{k-1-j}\left(\sum_{i=1}^n\binom{n-1}{i-1}(i-1)j^{n-i}+\sum_{i=1}^n\binom{n-1}{i-1}j^{n-i}\right)\\ &=\sum_{j=0}^{k-1}\frac1{j!(k-1-j)!}(-1)^{k-1-j}\left((n-1)\sum_{i=2}^n\binom{n-2}{i-2}j^{n-i}+\sum_{i=1}^n\binom{n-1}{i-1}j^{n-i}\right)\\ &=\sum_{j=0}^{k-1}\frac1{j!(k-1-j)!}(-1)^{k-1-j}\left((n-1)(j+1)^{n-2}+(j+1)^{n-1}\right)\\ &=\sum_{j=0}^{k-1}\frac1{j!(k-1-j)!}(-1)^{k-1-j}(j+1)^{n-2}(j+n)\\ \end{aligned} \]

直接枚举求解即可。Submission.

2026/06/07

CF715E Complete the Permutations

连边 \(p_i\to q_i\),则对于确定的 \({p_n}{q_n}\),最小步数为 \(n-环的数量\)。问题即转化为将给定的图补全,问环的数量固定时的方案数。

考虑已经固定的 \(x_1\to x_2\to\cdots\to x_k\) 这种链相当于一个单点。将原图收缩后,剩下的只有 \(\to x,x\to,\to\) 三种元素。(单点可以先不管,毕竟只要边定了,点填在哪也就定了)

设分别有 \(A,B,m\) 个。对于一个最终的环,我们将其中的非“\(\to\)”与相邻的“\(\to\)”合成,这样就能分层次地完成补全了:\(\to x,x\to\) 都可以内部消化,还可以与一个 \(\to\) 合成 \(\to\)

发现 \(\to\) 的个数不变,那就对于前两者写生成函数 \([x^k]F_1(x)=\sum_{i=k}^A\binom Ai{i\brack k}m^{\overline{A-i}}\)\(F_2\) 同理。\([x^k]F_3(x)={m\brack k}m!\),其中 \(m!\) 为单点的标号方案数。

暴力卷积即可。Submission.

2026/06/08

P3270 [JLOI2016] 成绩比较

发现科内的相对顺序是独立的,故设 \(f_{i,j}\) 为考虑前 \(i\) 科,恰有 \(j\) 人不被吊打的方案。转移就枚举新的状态中有 \(nj\) 人不被吊打,则 \(f_{i,j}\) 乘的系数为剩下 \(n-1-j\) 个人中恰好有 \(nj-j\) 个人排名在 B 之前。

二项式反演,变成至少 \(k\) 个人排名在 B 之前,系数为 \((-1)^{k-(nj-j)}\binom k{nj-j}\binom{n-1-j}i\binom{n-1-k}{r-k}\sum_{s=1}^U(U-s)^rs^{n-r-1}\),其中 \(r\) 为比 B 高的人数,\(U\) 为上限。

发现 \(\sum_{s=1}^U(U-s)^rs^{n-r-1}\) 只跟 \(U,r\) 有关,且拆开后可以化简为 \(\sum_{i=0}^rU^i\binom ri(-1)^{r-i}S_{n-i-1}(U)\),其中 \(S_k(n)=\sum_{i=1}^ni^k\)

可以考虑把 \(0\) 补上,则 \(S_k(n)=\sum_{i=0}^ni^k=\frac1{k+1}\left[(n+1)^{k+1}-\sum_{i=1}^k\binom{k+1}{i+1}S_{k-i}(n)\right]\)

此时时间复杂度降为 \(O(n^3m)\)Submission.

附:推导等幂和

posted @ 2025-08-28 21:23  flyingpg  阅读(11)  评论(0)    收藏  举报