题解:CF1954F Unique Strings

link

计数类 *3100 首次独立过纪念版题解。

首先我们考虑一个去重的问题。貌似针对循环同构去重的问题,只能从循环节上入手。

那么我们考虑设 dp(d) 为 最小循环节长度恰好为 d 不同方案数个数,则答案为:

d=1ndp(d)=d|ndp(d)d

这似乎是一条可行的路。但我们发现确定最小循环节长度是一个较为困难的问题,反而确定存在一个长度为 d 的循环节(直接固定,类似于二项式反演的思想)更为容易。

所以不妨有设 g(d) 为存在长度为 d 的循环节的方案数,则容易有 g(n)=d|ndp(d),因此由莫比乌斯反演我们知道 dp(n)=d|nμ(nd)g(d)

好了现在让我们来想想 g 的求法。

一个困扰我们的问题是原问题摆在了环上,但幸好我们可以将原题意转化为求解有多少个环状二进制串,满足 cnt1[c,c+k],存在一个全是一的连续段长度大于等于 c

如果说去掉环的限制显然是一个很 naive 的 DP 题,而环的限制本质上还是对同构提出了要求。

我们考虑字符串 S 的循环同构串数量,不妨设 SiSi 位置开始的循环串。则显然有设 xS 的最小循环节长度,有 Si=Si+x,且 S1Sx 互不相同。

这告诉我们 g(d) 其实也就是只需要考虑填这个串的 [1,d] 位即可,剩下的就是复制的问题了。

好了,现在我们可以考虑怎么去掉个数限制了。

为了方便统计,我们就强行要求 S[1]=0 吧。我们不妨设 fi,j,0/1 为在 [1,i] 中填写 j 个零,且最后一个零是 i,当前是否已经填过长度大于等于 c 的一连续段。

则对于 S1Sd 两两不同的限制就太简单了,这意味着只考虑 S[1,d],将其作为一个循环串,每个位置开头都不一样,这告诉我们如果我们将强制 S[1]=0,则对于任意一个使用了 t 个零的合法串,都恰有 t1 个与它同构,这告诉我们 fi,j,0/1j 就是填完 S[1,i],然后 [i+1,d] 全部写 1,所产生的贡献。

首先我们进行 O(n2) 的动态规划求出 f

就有 fi,j,tfi+x+1,j,t|[xc],初始 f1,1,0=1

这个转移显然可以使用差分进行优化。

接着我们有 si,j,t=xjfi,x,tx

然后我们就可以考虑着手求出 g 了。

对于 gd,由于它要复制 nd 次,我们可以求出其能够填写的零的个数的范围 [l,r],同时枚举最后一个零的位置 i[1,d],注意到 [i+1,d] 全部写一,利用 s 进行统计即可。

但是我们需要注意到可能会出现类似于统计 g(6),对于串 011011 这种答案。

我们发现这个串是应该属于 dp(3)。在这里还多除以了一个 2,因此这提示我们可能需要更改一下朴素的莫比乌斯容斥系数。

一个很简便的方法是:将所有的 d 直接化为 n,也即直接乘上 dn,这样就去除了这种多除的问题。然后最后算答案的时候 dp(d) 再乘上 nd 即可。

复杂度 O(n2+d2(n)+d|nd)=O(n2)

posted @   spdarkle  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示