Loading [MathJax]/jax/element/mml/optable/MathOperators.js

SDSC2020题解(部分)

好不容易把省队集训的题重新写了一遍,当然是只写了自己比较会的题QAQ,所以来总结下写过的题的题解,如果哪里写错了请大佬指正QAQ,没写的题写完会补上

Day 1

这天的题有点毒瘤,先跳了

Day 2

T1

T2 仙人掌

首先我们知道只保留编号在[l,r]的点时,联通块数=点数-边数+环数

那么考虑枚举右端点,对于每个左端点用线段树维护答案

于是只需要考虑新加进来一个点的贡献:点数+1,和r相连的边到达的点如果比r小就算贡献,所有编号最大值是r的环也要算贡献

因为是仙人掌,所以我们可以用求圆方树来求出每个环的编号最小值和最大值

Day 3

T1 如何优雅的送分

2F(i)可以看作枚举i的质因子集合的子集,那么考虑直接枚举每个子集d,那么有nd个子集包含它,所以原式变为了

ni=1μ2(i)ni

=ni=1μ(i)i2|dnd

=ni=1μ(i)ni2j=1ni2j

这个式子就可以直接做了

T2 阴阳

看着就非常可持久化点分树,我的可持久化点分树写法是:对每个点开动态开点线段树,每次对在点分树上修改的logn棵线段树建立新版本,再用主席树维护每个点各个版本对应的信息

T3 你猜是不是找规律

题目的实质是问一个长度为n的排列,交换k次能得到多少本质不同的排列

考虑一个简单的dp,设f[n][k]表示长度为n的排列交换了k次得到本质不同的排列个数,只考虑第n位,要么不参加交换,要么交换一次,那么转移方程有f[n][k]=f[n][k1]+f[n1][k1]×(n1)

k一定的时候f[n][k]是个关于n的多项式,这个多想是的次数我们可以通过差分得到是2k1次,最后答案求前缀和也就是2k次多项式,直接拉格朗日插值就可以了

Day 4

T1 树论

答案转化为所有距离x深度不超过d的边权和2该联通块的直径

那么我们考虑线段树合并,维护每个深度的联通块边权和和直径,然后有一个显然的结论,两个联通块的直径端点分别是a,b,c,d,那么合并后新的直径也一定是在这4个点之中

T2 图论

考虑对两种路线建不同的边

第一种路线建两棵以最大值为根的笛卡尔树,一棵由儿子向父亲连边,另一棵由父亲向儿子连边(边权均为0),然后对应点连这个点的点权的边,每次走的一定是两点的lca,也就是最大值

第二种路线建两排辅助点,大概是这样子(懒得画图了就只好搬原题解的图了QAQ)

这样最短路一定会走最短的那条边

T3 几何

凸多边形划分后原多边形的边一定在三角形上,三角形把这个凸多边形划分成了两部分,而这两部分的生成树的导出子图只有两种情况,要么是一棵树,要么是两棵树(因为在三角形上的边的端点只有两个)

那么我们可以根据这个进行dp,设f[i][j]表示(i,j)这条边分割出来ij这些点对应第一种情况的方案数,g[i][j]就表示对应第二种情况的方案数。

然后找到三角形的另一个端点x,则有转移式

f[i][j]=f[i][x]×g[x][j]+g[i][x]×f[x][j]+f[i][x]×f[x][j]

g[i][j]=f[i][x]×g[x][j]+g[i][x]×f[x][j]

具体就是看看i,j这条边选不选,然后从1,n开始dp就可以了

而我们有用的状态只有2n3个,如果枚举找xO(n2)的,用set找就变成了O(nlogn)

Day 5

T1 毒瘤约数

由2条件可得D[i]|N,对3条件做均值不等式可得出D[i]

那么我们可以直接对N的约数建图跑最长反链

然后我们猜想最长反链一定是在多层图中的某一层,于是我们可以对N的质因子构造一个生成函数,直接算答案(为什么是对的我也不知道QAQ)

T2 毒瘤树

题目其实就是让你求直径在[l,r]的联通块个数

这个东西我们可以首先转化为前缀和的形式,于是我们只需要求直径小于等于R的联通块个数

那么考虑树上dp,设f[u][d]表示u为最浅点,最深点距离ud的联通块个数,那么有转移方程

f[u][max(d1,d2+1)]=\sum_{d1+d2+1\le R}f[u][d1]\times f[v][d2]

然后考虑优化这个式子,那就把max拆开,则有方程

f'[u][d2+1]+=\sum_{d1+d2+1\le R\&d2+1>d1}f[u][d1]\times f[v][d2]

f'[u][d1]+=\sum_{d1+d2+1\le R\&d1\le d2+1}f[u][d1]\times f[v][d2]

第一个式子可以用前缀和优化

而对于第二个式子,这个看起来像加上一个数的x倍,而注意到刚开始f'[u][d1]=f[u][d1],那也就是乘x+1

因此我们用线段树对第一个式子维护单点修改,第二个式子维护区间乘,然后记录每个数被乘了多少次可以用map维护

这样子复杂度是O(n^2log(n))

那么我们对其长链剖分,每次先dp深度最深的儿子,那么第一次只需要转移f[u][d+1]=f[u][d],而当按dfs序优先对长链标号后,这个就相当于区间平移,那么问题就游刃而解了

复杂度O(nlog(n))

T3 毒瘤题面

如果一个数x在长度为n的区间出现了c次,那么其对答案的贡献为2^{n-c}\times(2^c-1)x=x(2^n-2^{n-c}),具体就是不包含x的序列个数乘包含x的序列个数

那么我们可以用一个莫队来统计答案,而模数每次不同比较的棘手

可以注意到一个长度为n的序列本质不同的出现次数是不超过\sqrt{n}的,因为1+2+3+...\sqrt{n}=n,那么我们用链表存下来,统计的时候暴力算就好了

快速幂的话还需要用光速幂

复杂度O(n\sqrt{q}+q\sqrt{n})

Day 6

T1 简单题

对题目简单化式子可以发现1^K(R)的意义是选K个数乘积为R的方案数

我们注意到K是一个非常大的,而一个数被整除log次就变成1了,所以一定会有非常多的1,于是可以考虑去掉1的情况进行dp

f[n][k]表示选k个非1的数乘积是n的方案数,那么可以这么转移

f[n][k]=\sum_{d|n\&d\ne1}f[\frac{n}{d}][k-1]

k枚举到log就可以了,而通过刷表也就是类埃氏筛的做法可以将复杂度做到O(nlog(n)loglog(n))

然后剩下的1就非常的好办,只需要考虑把这些1看成物品,而方案就是把k个因数替换掉1的方案数,也就是C_{K}^{K-k}=C_{K}^k

那么最后的答案

∑_{i=L_j}^{R_j} 1^{K_j} (i)=\sum_{i=L_j}^{R_j}\sum_{k=0}f[i][k]\times C_{K}^k

f可以通过前缀和查询区间,C_K^k可以递推得出

T2 简单三角

一个三角形的简单值可以通过皮克定理求得,剩下的就是一个裸的三元环计数

先根据度数把边定向,枚举边,再一个端点,将端点到达的点标记,再枚举另一个端点到达的点,如果有标记就是一个三元环

复杂度O(n\sqrt{n})

注意下要把点和边去重,不然复杂度是错的

Day 7

T1 a xor b problem

考虑如何把a进制转成b进制

那么回忆a进制转10进制的过程

\sum_{i=0}^nx_i\times a^i

b进制下做这个式子就可以了

而这题有高精,那么考虑如何加速这个过程

\sum_{i=0}^nx_i\times a^i=\sum_{i=0}^{\frac{n}{2}-1}x_i\times a^i+a^{\frac{n}{2}}\times\sum_{i=0}^{\frac{n}{2}}x_{i+\frac{n}{2}}\times a^i

左右两个和式可以递归做下去,中间的a^{\frac{n}{2}}\times\sum_{i=0}^{\frac{n}{2}}x_{i+\frac{n}{2}}\times a^i可以用fft加速

时间复杂度O(nlog^2(n))

T3 猜数游戏

我们考虑n=3,k=2的时候怎么做

先猜两次0,如果全是否那么一定是真话

不然在第一次说是之后问一个1

如果回答是那么答案一定在0,1之中,所以一定不是2

如果回答否那么一定不是1

所以我们一定可以排除一个数字

n,k变大之后怎么做

一样按上面的思路,先问k0,全是否那么一定是真话,否则就在第一次回答是的时候进行询问

那么我们现在有2^{k-1}个数,有k-1次询问,于是可以考虑二进制划分,每次询问编号有2^i的数,通过k-1次询问后可以唯一确定一个数

posted @   eee_hoho  阅读(413)  评论(0编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· MQ 如何保证数据一致性?
点击右上角即可分享
微信分享提示