Anhao Li
Assorted Problems 3Blur image

Mostly old Luogu blue-difficulty problems I solved years ago — quick sketches plus short editorials.

P4317 The Flower God’s Number Theory Problem#

problem link

The answer is clearly Πicnt[i]\Pi i^{cnt[i]}, where cnt[i]cnt[i] is the number of times ii ones appear.

There’s a fairly obvious digit-DP approach, but it turns out I computed it with binomials.

Go from the high bits down. Suppose the current bit of NN is 1: place a 11 everywhere you can before this position, leave this bit as 0, and then the remaining bits are free. Binomials handle the rest.

https://www.luogu.com.cn/paste/8ftcv19a

P4430 Monkey Fight#

problem link

My favorite kind of find-the-pattern problem (not really).

Somewhere in the back of my memory is something called a Prüfer sequence, from which the number of labeled unrooted trees is nn2n^{n-2}.

Each such tree has n1n-1 edges, so the number of generated orders is (n1)!(n-1)!.

Multiply the two.

https://www.luogu.com.cn/paste/5rfn8cdq

P4514 God’s Seven Minutes of Problem Setting#

problem link

Tree-of-trees at a glance.

Looking at my code, it’s a 2D BIT.

Difference arrays on top of difference arrays give range add and range sum.

https://www.luogu.com.cn/article/u4lh1j1n

P4550 Collecting Stamps#

problem link

Brain a little foggy.

Couldn’t derive an expected-value DP this simple. Rough.

https://www.luogu.com.cn/article/u3ul4p52

CF1000F One Occurrence#

problem link

Mo’s algorithm + set at first glance. Looking at my code, you don’t need a set — a stack works: record each element’s position in the stack, and to delete, swap with the top and pop.

Since it’s offline anyway, you can also sweep: sort the intervals by right endpoint.

Then for each value keep only its rightmost occurrence, and at that position record the previous occurrence, say pre[i]pre[i]. A range query then asks whether the minimum pre[i]pre[i] is <l<l; if so that value appears exactly once. Maintain minima and positions with a segment tree.

https://www.luogu.com.cn/article/5nv0adca

P4822 [BJWC2012] Freeze#

problem link

Layered graph + shortest path at a glance, though the constraints felt odd.

Looking at my code, there’s no problem. My mistake.

Build KK layers, and when connecting a layer to the one below, halve the weight.

https://www.luogu.com.cn/paste/4hwtsh6g

CF1006F Xor-Paths#

problem link

One look at the submission timestamp told me I probably didn’t write this code.

Thought about it for a while with no ideas.

One glance at the “search” tag and it clicked.

Split along the diagonal and do meet-in-the-middle.

https://www.luogu.com.cn/article/6kwz3c7z

P4910 Patchouli’s Bracelet#

problem link

DP plus matrix optimization at a glance.

But I’d blown up the DP state so it couldn’t be optimized at all. Unbelievable.

You don’t need the first element in the state at all — just adjust the initial values and case-split.

https://www.cnblogs.com/liangbowen/p/16945276.html

P5021 [NOIP 2018] Building Tracks#

problem link

Ancient memories.

First, it’s easy to see you binary search the answer for the minimize-the-maximum part.

Above that, do a tree DP.

Each node can pass at most one track upward, so pair up its children’s tracks (binary search or a multiset both work) and pass the longest leftover upward.

https://www.luogu.com.cn/paste/bnbfvrsg

CF1076E Vasya and a Tree#

problem link

I remembered it as a tree difference array but couldn’t recall how.

Looking at the code: you can hang all the modifications on the tree offline first, then apply the difference during the dfs, using a BIT to record difference values per depth and prefix-sum them. The dfs itself guarantees the difference values come only from the current node’s ancestors, and you remove the value on backtrack.

https://www.luogu.com.cn/paste/y1v2id1i

P5122 [USACO18DEC] Fine Dining G#

problem link

First instinct was to build the graph and run a shortest path from n — and then I was stuck.

One skim of the editorial showed it isn’t hard; my thinking had gotten rigid.

Let dis[i]dis[i] be the shortest path distances. If node ii has a haystack a[i]a[i], add a virtual node (n+1)(n+1) connected to ii with weight dis[i]a[i]dis[i]-a[i], then run another shortest path from n+1n+1 to get a second distance array and compare.

https://www.luogu.com.cn/paste/jawppchr

P5123 [USACO18DEC] Cowpatibility G#

problem link

Brute-force inclusion-exclusion at first glance, and I came up with a bogus version of it. Unbelievable.

Each cow gives 252^5 inclusion-exclusion terms — but how do you count each result?

Looking at my own code, it’s delightfully brute force: sort the chosen numbers ascending, insert a separator between them to form a string, and store it all in a map. Not bad.

https://www.luogu.com.cn/paste/rlmxpht1

P5268 [SNOI2017] A Simple Query#

problem link

Blanked for a moment, then remembered it resembles a THUWC problem.

Consider a single value xx first, with a prefix sum sum[i]sum[i] counting occurrences of xx in the first ii elements.

The contribution of xx is (sum[r1]sum[l11])(sum[r2]sum[l21])(sum[r_1]-sum[l_1-1]) * (sum[r_2] - sum[l_2-1]).

Expand with the distributive law and it becomes a product of two prefix sums, which Mo’s algorithm handles easily.

https://www.luogu.com.cn/paste/95s712lj

P5304 [GXOI/GZOI2019] Traveler#

problem link

Brain-lapse, didn’t get it. The extra-log approach feels more interesting than the intended solution.

https://www.luogu.com.cn/article/oow8gs0r

P5505 [JSOI2011] Distributing Specialties#

problem link

I had the rough idea — inclusion-exclusion — but forgot about stars and bars. A bit embarrassing.

https://www.luogu.com.cn/article/ifavg4dm

CF1197D Yet Another Subarray Problem#

problem link

I came up with a silly approach that might also pass?

Looking at my old code, it’s just a DP: group by residue, DP backwards, and maintain the suffix. Let f[j]f[j] be the DP value for right endpoints with i%m=ji\%m=j.

At each ii, either set f[i]=sum[i]f[i]=sum[i] or keep the previous one, then update with f[i]kf[i]-k.

Take the max of the two.

Then with ii as the left endpoint, consider the contribution of the right endpoint for each residue.

https://www.luogu.com.cn/paste/vr2e3ait

P5589 Peppa Pig Plays a Game#

problem link

I got the DP recurrence and the pattern, but one detail wrong. Not too bad.

The general idea matches this:

https://www.luogu.com.cn/article/c187nysw

CF1238F The Maximum Subtree#

problem link

I mostly worked out the properties, came up with a weird DP, then looked at my code and the editorial.

Turns out I’d just used a greedy. Interesting — silly me.

https://www.luogu.com.cn/paste/ed6j9k3r

CF1238E Keyboard Purchase#

problem link

I saw it needed bitmask DP but couldn’t see how to account for the contribution. A bit of a blowup.

Looking at my old code, it’s rather neat: for each state, on each transition add the pairwise contribution between the set and its complement. Then when a letter enters the set, the number of times it has been counted beforehand is exactly the keyboard distance.

Easier to follow from the code.

https://www.luogu.com.cn/paste/imhc56ui

CF1303E Erase Subsequences#

problem link

DP at a glance, and you can get there with a bit of thought.

Enumerate the length of s1s1, then let f[i]f[i] be the maximum number of characters of s2s2 matchable when s1s1 is matched up to position ii.

The DP isn’t hard; the code makes it clear.

https://www.luogu.com.cn/paste/hq2qo9u2

P6186 [NOI Online #1] Bubble Sort#

problem link

https://www.luogu.com.cn/article/duay9pls

P6275 [USACO20OPEN] Sprinklers 2: Return of the Alfalfa P#

problem link

Analyzed it wrong. Doomed.

Drawing it out, the boundary between the two parts is always a staircase from the top-left to the bottom-right, so DP over that staircase: let dp[i][j][0/1]dp[i][j][0/1] be the state at cell (i,j)(i,j) with the staircase heading right or down.

Simple DP plus counting.

https://www.luogu.com.cn/paste/umu66048

CF1365F Swaps Again#

problem link

Zero ideas. Doomed.

You just need to guess the right lemma — and guessing lemmas used to be my strongest skill.

https://www.luogu.com.cn/article/w8jhbqpz

P1857 Prime Stone Game#

problem link

A true classic, but years without training have slowed my brain.

It’s Grundy values first, computable with a linear sieve, building the SG array as the statement requires.

Then DP: for winning states finish as early as possible, for losing states delay as long as possible.

The transitions follow from the SG array.

Easier to follow from the code.

https://www.luogu.com.cn/paste/q8l5n8ih

P2606 [ZJOI2010] Counting Permutations#

problem link

I saw it was a min-heap immediately and hand-waved a DP that looked about right.

Let f[n]f[n] be the number of min-heaps on nn nodes. Take 1 as the root each time, split into two subproblems, multiply the counts and a binomial:

f[n]=f[l]f[r]Cn1lf[n]=f[l]*f[r]*C_{n-1}^{l}

There’s a detail issue — build a heap in advance to compute the left subtree’s size.

https://www.luogu.com.cn/paste/5bptgon9

P2743 [USACO5.1] Musical Themes#

problem link

I came up with a horribly convoluted approach and completely missed that you just take differences and DP.

f[i][j]f[i][j]: the first part ends at ii, the second at jj. Routine transitions.

https://www.luogu.com.cn/paste/sd8mu4o0

P3620 [APIO/CTSC2007] Data Backup#

problem link

Brain-lapse: after taking differences it’s just the tree-planting problem — the classic regretful greedy.

https://www.luogu.com.cn/paste/kcqz94b7

P3545 [POI 2012] HUR-Warehouse Store#

problem link

Max flow at a glance, then I realized it needs min-cost flow.

And then that it’s really just simulated min-cost flow (regretful greedy).

A priority_queue does the job.

https://www.luogu.com.cn/paste/uh0ia6ux

CF900D Unusual Sequences#

problem link

My analytical ability is gone.

Let g(y)g(y) be the number of sequences summing to yy, ignoring the gcd\gcd constraint.

It isn’t hard to see g(y)=2y1g(y)=2^{y-1}, by stars and bars: each gap is either split or not.

Let f(x)f(x) be the number of sequences summing to xx with gcd=1\gcd =1.

Then g(k)=dkf(k/d)=2k1g(k)=\sum\limits_{d|k}f(k/d)=2^{k-1}

By inclusion-exclusion,

f(k)=g(k)dk,d>1f(k/d)f(k)=g(k)-\sum\limits_{d|k,d>1}f(k/d)

Just recurse.

https://www.luogu.com.cn/paste/e7ko1cep

CF895C Square Subsets#

problem link

My thinking went sideways into DP, which does work, but a linear basis is the fastest approach.

First, aia_i is small and there are only 19 primes <=70<=70, which suggests a linear basis.

Let S|S| be the size of the basis after inserting everything.

Then the remaining nSn-|S| numbers are linearly representable.

So the answer is 2nS12^{n-|S|}-1.

https://www.luogu.com.cn/paste/rv65zn8y

CF741C Arpa’s overnight party and Mehrdad’s silent entering#

problem link

I thought it was 2-SAT. Naive of me.

Build a bipartite graph and color it.

Couples obviously get an edge.

The “two of any three must differ” constraint gives edges (2i1,2i)(2i-1,2i).

The result is always bipartite: any cycle alternates a couple edge with an adjacency edge, so every cycle is even and no odd cycle exists.

https://www.luogu.com.cn/paste/81eqdo46

CF730I Olympiad in Programming and Sports#

problem link

Min-cost flow construction at a glance.

But regretful greedy (simulated min-cost flow) also works.

https://www.luogu.com.cn/article/2ensxnz4

Code:

https://www.luogu.com.cn/paste/l0g3abms

CF623B Array GCD#

problem link

Fun one.

The key realization: since you can’t delete everything, either the first or the last number survives.

So you only need the prime factors of those two numbers across six cases (plus one, minus one, unchanged).

Sieve them out first, then DP with each prime factor as the gcd\gcd.

Let f[i][0/1/2]f[i][0/1/2] be the minimum cost at element ii with nothing deleted, currently deleting, or done deleting.

The transitions aren’t hard; see the code.

Once you get step one, the rest is routine.

https://www.luogu.com.cn/paste/d1zcnjfe

CF521D Shop#

problem link

I remembered the approach but had misread the statement.

The order of operations is always assign, then add, then multiply.

For assignment keep only the largest per position, which converts assignment into addition.

Sort the additions descending, which converts them into multiplications.

Finally sort the multiplications descending and output the first mm.

https://www.luogu.com.cn/paste/9iffudq6

CF486D Valid Sets#

problem link

Inertia again: I saw the constraints and immediately wanted a two-dimensional DP state.

Since the constraints are so small, just enumerate each node, force it to be the maximum, and DP with it as the root:

f[u]=f[u]+f[u]f[v]f[u] = f[u] + f[u]*f[v]

which is essentially a knapsack merge.

https://www.luogu.com.cn/paste/xqad5b23

CF19E Fairy#

problem link

Took me forever to even understand the statement.

It asks which edges, when removed, leave a bipartite graph.

The criterion for bipartiteness is the absence of an odd cycle.

The answer is the intersection of all odd cycles that appear.

A dfs handles it.

https://www.luogu.com.cn/paste/edls0m5o

P4161 [SCOI2009] Game#

problem link

https://www.luogu.com.cn/article/zmgkp11r

AT_arc070_b ABC056D No Need#

problem link

The key here is that element ii is not dispensable exactly when the rest cannot build up [Kai,ai][K-a_i,a_i].

First instinct: run a knapsack and then remove items one at a time — since a knapsack can be read as a polynomial, removal is dividing by a polynomial. Looking at my code, I instead optimized the DP with CDQ divide and conquer. The editorial has another approach that’s quite interesting: [[https://www.luogu.com.cn/article/o87199on]]

my code: https://www.luogu.com.cn/paste/ds9v7cib

AT_agc010_b AGC010B Boxes#

problem link

No ideas beyond difference arrays. Blew it, went to the editorial.

Half the editorials got details wrong, ugh. It’s a rather clever thinking problem. Each operation decreases the total by n(n+1)2\frac{n(n+1)}{2}, so a solution exists only when M=ia[i]n(n+1)2\large M=\frac{\sum_i a[i]}{\frac{n(n+1)}{2}} is an integer.

Now look at the difference array: each operation does d[i]=d[i]+(n1)d[i]=d[i]+(n-1) at one index and d[j]=d[j]1d[j]=d[j]-1 everywhere else. Let mim_i be the number of type-one operations at position ii. That gives the equation d[i]+mi(n1)(Mmi)=0d[i]+m_i(n-1)-(M-m_i)=0

which solves to mi=Md[i]nm_i=\frac{M-d[i]}{n} and that settles the problem — just check that every mim_i is non-negative.

https://www.luogu.com.cn/paste/76krqu56 btw, I’m not quite sure how to reduce this problem to a general class.

AT_arc063_c ARC063E Trees and Integers#

problem link

Small brain-lapse. There’s an obvious construction: push all the initially weighted nodes into a priority queue, repeatedly pop the largest, and assign its unassigned neighbors that node’s weight minus one. Then check validity at the end.

https://www.luogu.com.cn/paste/ts26d0ak

AT_agc004_c AGC004C AND Grid#

problem link

Nice construction. Noticing the border is never covered, you can construct the two grids like this:

###. ....# 
#.... #### 
###. ....# 
#.... #### 
###. ....#
plaintext

and then just color in the original grid’s cells.

https://www.luogu.com.cn/paste/oa3ylcch

CF1051F The Shortest Statement#

problem link

It isn’t hard to see you should pull out a spanning tree first. The remaining non-tree edges touch at most 42 nodes; call those special. Run Dijkstra from each special node to get its distances to everything. For a query, first get the tree distance via LCA, then enumerate the special nodes and check whether forcing a path through one is shorter. Easy to implement. https://www.luogu.com.cn/paste/89h3fi2e

CF1234F Yet Another Substring Reverse#

problem link

I got most of the way there but not all of it. The constraints immediately suggest bitmasks. But S|S| is large, which confused me. Analyzing calmly: what you actually need is two intervals s1,s2s1,s2 with s1&s2=0s1 \& s2=0 maximizing the popcount of s1s2s1|s2. A high-dimensional prefix sum does it: for each character set, sum its answer with its complement’s. https://www.luogu.com.cn/paste/vi8s04gg

P1989 Counting Triangles in an Undirected Graph#

problem link

Why is this idea so clever? One look at the 10510^5 constraint and it felt hopeless — I broke into a sweat and went to the editorial, only to find I’d written this problem shortly before retiring in high school (sigh). First, turn each undirected edge into a directed one, from lower degree to higher degree, breaking ties by smaller index. Then you can brute-force it. For each node uu, mark all its neighbors, then enumerate each neighbor vv, then enumerate each neighbor ww of vv and check whether ww is marked by uu; if so, add 11 to the answer. Why is the complexity fine? Consider the nodes one at a time: the complexity is each node’s in-degree times its out-degree.

If a node’s degree in the original graph is <=m<=\sqrt{m}, its out-degree is certainly <=m<=\sqrt{m} too. If its degree is >m> \sqrt{m}, it only points to nodes of higher degree, of which there are at most m\sqrt{m}, so its out-degree is also <=m<=\sqrt{m}. For in-degree, consider each original edge (u,v)(u,v): its contribution to the complexity is out[v]out[v], and since out[v]<=mout[v]<=\sqrt{m} as proven above, the total complexity is O(mm)O(m\sqrt{m}).

https://www.luogu.com.cn/paste/9g86u6as

AT_agc033_c AGC033C Removing Coins#

problem link

I never thought in this direction. Silly me.

You only need the diameter length: each operation reduces it by 1 or 2, so compute the diameter and check it mod3\mod 3. You can also derive it with Grundy values.

https://www.luogu.com.cn/paste/9h9kwq6m

AT_arc100_c ARC100E Or Plus Max#

problem link

My thinking got rigid: high-dimensional prefix sum at a glance, but then I didn’t see how to handle ai+aja_i+a_j.

Looking at my code, you just track the largest and second largest while doing the high-dimensional prefix sum. Obvious in hindsight, and I still missed it. Remember the constraint is <=<=, so take a prefix maximum at the end. https://www.luogu.com.cn/paste/m1mn89hu

AT_arc115_d Odd Degree#

problem link

The easiest observation is that an odd number of odd-degree vertices is impossible, so only even kk has an answer. Consider the tree case first. If you fix which kk vertices have odd degree, every tree edge’s inclusion is determined (work up from the leaves). Likewise, once you add some non-tree edges, the tree edges’ states are still determined. With nn vertices and mm edges in total, forcing kk vertices to odd degree gives 2mn+1C(n,k)2^{m-n+1} * C(n, k) ways, and then you merge across connected components with a knapsack. The hard part is analyzing the tree case first.

code

AT_arc122_d XOR Game#

problem link

For XOR problems there are only so many angles. Go from the high bit down. If the count of 1s at this bit is odd, the final answer is determined at this bit: you just need to find which 0-at-this-bit element to pair with which 1-at-this-bit element to minimize the answer, since the second player decides. A trie solves it. If the count of 1s at this bit is even, they pair up perfectly, this bit ends as 0, so split the numbers by this bit and continue at the next one.

code

AT_arc124_d Yet Another Sorting Problem#

problem link

Start with the unrestricted case where you may swap freely: link ii to p[i]p[i] to get a set of cycles, and a cycle of length lenlen needs len1len - 1 operations to put every position in place. Each cycle is clearly independent. For this problem, a cycle spanning both halves also takes only len1len - 1 operations. If all of a cycle’s nodes are on the left, you must add two edges to join it with some cycle (or single node) on the right, forming one big cycle. With s1s1 cycles on the left, s2s2 on the right, and gsgs cycles total, the answer is n+mgs+2max(s1,s2)n + m - gs + 2 * max(s1, s2). The single-node case needs special handling.

code

AT_arc126_d Pure Straight#

problem link

First, KK is tiny, so bitmask DP. Now, how to design the state? Let f[i][S]f[i][S] be: considering position i, having fixed the values in state SS. For position i, if a[i]a[i] doesn’t appear in SS, you can take it — count how many elements of S are larger than it, since those must all be swapped with ii, contributing that much (i.e. the inversion count), then transition into the state containing a[i]a[i].

Or you can skip a[i]a[i]: compare whether it’s better to move everything already chosen past i, or to move everything chosen later past i, and take the min. This counts as a DP with contributions computed in advance.

code

CF11D A Simple Task#

problem link

Hadn’t woken up.

The constraints say bitmask DP at first glance, and the key is forcing the smallest index as the start. Let f[S][i]f[S][i] be the number of paths covering the set SS with current endpoint ii; the transition is then easy, just enumerate the neighbors of ii. Note that walking an edge back and forth, and each cycle being counted twice, means the answer is ansm2\frac{ans - m}{2}.

code

CF19E Fairy#

Right direction, but I never nailed down the details. Getting old, can’t push through the properties any more qwq

solution

CF165E Compatible Numbers#

problem link

Textbook high-dimensional prefix sum.

CF367E Sereja and Intervals#

problem link

Misread the constraints. Blew it.

solution

Assorted Problems 3
https://www.lomit.top/en/blog/icpc/%E6%9D%82%E9%A2%98%E4%B9%B1%E5%81%9A3
Author Anhao Li
Published at May 11, 2025