【比赛题解】NOIP2021 题解

 


T1. 报数

LOJ #3564

Solution

可以先把十进制表示下数位含有 7 的所有数都求出来,然后去枚举这些数的倍数,将其标记。

如果当前枚举到的数被标记过了则就不需要再枚举倍数了(因为枚举的倍数肯定也被标记过了)。

标记出所有需要跳过的数后,从后往前预处理一遍答案即可。

类似埃筛,时间复杂度 O(nloglogn)

T2. 数列

LOJ #3565

Solution

注意到直接在序列后加入一个数会比较难维护,可以考虑从小到大向序列中加数。

f(i,j,h,S) 表示:已经选了 j 个数,选出的数的值域为 [0,i],二进制表示中的 [0,i] 位中有 h1[i+1,] 中的二进制表示为 S 时的方案数。

可以考虑枚举选了多少个 i。假设选了 xi,那么就有转移:

f(i,j,h+(S+x)mod2,S+x2)+f(i1,jx,h,S)vix(jx)

最后答案即为:h+count(S)kf(m,n,h,S)

其中 count(S) 表示 S 二进制表示下 1 的个数。

时间复杂度 O(n4m)

T3. 方差

LOJ #3566

Solution

简单处理可以把方差的 n2 倍化为:

n(i=1nai2)(i=1nai)2

那么,只需要知道一个序列的数值和数值平方和,就可以计算出该序列的方差了。

记差分数组 bi=aiai1,那么一次对 i 的操作就相当于交换 bi,bi+1

由于邻项交换,并且可以进行任意多次操作。
那么所有操作结束后的新差分数组 {b} 可以是原差分数组 {b} 的任意一个排列。

一个结论:最优解的差分数组一定是先递减、后递增的(也就是单谷的)。

根据这个性质,我们就可以先将所有的 n1 个差分值从小到大排序,然后从小到大加入差分值。由于方差关系的是数据之间的相对大小,我们不妨钦定一个基准点,它的值为 0

sumi 表示前 i 小的差分值之和是多少。

f(i,S) 表示:考虑到前 i 个差分值,当前的数值和为 S 时,数值平方和最小是多少。

若向当前序列的左端加数,则有转移:

f(i,S+bii)minf(i1,S)+2Sbi+ibi2

若向当前序列的右端加数,则有转移:

f(i,S+sumi)minf(i1,S)+sumi2

最后的答案即为 min{nf(n1,S)S2}

设值域为 m,直接做显然是 O(n2m) 的。

但是注意到整个序列 {a} 中不同的数总共就只有 min(n,m) 个,也就是说差分数组中不为 0 的有效差分值不超过 min(n,m) 个,于是就可以优化到 O(min(n,m)nm)

T4. 棋局

LOJ #3567

Solution

(待填 ...)

posted @   Calculatelove  阅读(450)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示