NOI2016

P1117 [NOI2016] 优秀的拆分

  • 首先一个很明确的方向就是对于每一个拆分的位置算贡献

  • 也就是对于每个位置求出前面有多少个形如 AA 的子串,求出后面有多少形如 BB 的子串,答案就是所有位置两者相乘的和

  • 而实际上前缀和后缀是一样的,无非是将子串翻转一下再做,所以考虑一种就可以了

  • 一个暴力的做法就是 O(n2) 用 Hash 判断,然而这样就有了 95 分了(多少有点随意了......),考虑最后的 5 分怎么拿

  • 讲实话正解不是很好想,考虑枚举每一个 A 可能的长度,然后以 len,2len,3len,... 为关键点

  • 那么 AA 一定会经过恰好两个相邻关键点

  • 那么我们考虑对于两个关键点求贡献,求出 lcp(i,j),lcs(i,j) ,根据这个可以算出通过这两个关键点的 AA 的范围,对于这个范围整体 + 1,这个可以差分做

  • 对于 lcp,lcs 考虑 SAM 的做法就是求 parent 树上的 lca 的深度,那么考虑用 ST 表求正串和反串的 parent 树的 lca

  • 关键点对的数量是一个调和级数,所以总的复杂度是 O(nlogn)

总结

  • SAM

  • 关键点的想法确实是很难想的,难怪 n2 会给到 95 分,不过两者思想的差距确实还是很大的

P1587 [NOI2016] 循环之美

  • 考虑在 k 进制下的循环小数 xy ,设 {x} 表示 x 的小数部分,设 l 为循环小数的长度

  • 那么 {xy×kl}={xy}

  • 那么 xyklxykl=xyxy

  • 那么 xkl=xy×(int),那么 xklx(mody)

  • 那么 kl1(mody),那么 k1(mody),gcd(k,y)=1

  • 那么其实就是要求 :

    i=1nj=1m[gcd(i,j)=1][gcd(j,k)=1]

  • 下面就是开始推式子了

i=1nj=1md|id|jμ(d)[(j,k)=1]d=1nμ(d)ndj=1m[d|j][(j,k)=1]d=1nμ(d)ndj=1md[(jd,k)=1]d=1nμ(d)nd[(d,k)=1]j=1md[(j,k)=1]

  • 那么第一层确定为数论分块了
  • f(n)=i=1n[(i,k)=1],这个拿 μ 反演一下就是 d|kμ(d)nd ,这一部分的复杂度就是 O(k)
  • g(n,k)=i=1nμ(i)[(i,k)=1]

g(n,k)=i=1nμ(i)[(i,k)=1]=i=1nμ(i)d|id|kμ(d)=d|kμ(d)d|iμ(i)=d|kμ(d)i=1ndμ(id)

  • 考虑将最后的一个式子拆开,注意到如果 gcd(i,d)1 ,那么 μ(id)=0

g(n,k)=d|kμ(d)2i=1ndμ(i)[(i,d)=1]=d|kμ(d)2g(nd,d)

  • 边界为 g(0,k)=0,g(n,1)=d|nμ(d) ,这个就直接杜教筛

  • 事实上这个东西的复杂度在于杜教筛,所以为 O(n23)

  • 总的复杂度就是 O((k)n+n23)

posted @   Kzos_017  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示