您的位置:首页 > 其它

SDOI2017 Round1 解题报告

2017-04-19 19:37 183 查看
蒟蒻花了三天才补完(然而ATP大佬场上A了五道题)为了整篇解题报告的长度,代码就不粘在这里啦。

数字表格

这题啊。。没有想出来。看到连乘就懵逼。

先假设n< m啦。

∏nd=1∏ni=1∏mj−1f[d] (如果gcd(i,j)==d)就乘上。

∏nd=1∏n/di=1∏m/dj−1f[d](如果gcd(i,j)==1)就乘上。

于是发现要维护这么一个函数cnt(x,y)=∑xi=1∑yj=1[gcd(i,j)==1](x< y)

qwq反演基本题型。

cnt(x,y)=∑xk=1μ(k)∗(x/k)∗(y/k)

这东西可以sqrt(x)的复杂度算

ans= ∏nd=1f[d]cnt(n/d,m/d)

ans= ∏nd=1f[d]∑n/dk=1μ(k)∗(n/d/k)∗(m/d/k)

然后观察d和k的枚举,就是在枚举dk<=n,所以我们先枚举dk的值(T=dk)

ans = ∏nT=1∏k|Tf[T/k]μ(k)∗(n/T)∗(m/T)

设g(T)=∏k|Tf[T/k]μ(k)

ans=∏nT=1g(T)(n/T)∗(m/T)

如果处理出来了g函数的前缀积以及前缀积的逆元,ans就能在(O(n√∗logn)的时间内计算出来

计算g的方式可以用类似埃氏筛法的东西O(nlnn)计算

然后处理前缀积 ,再算逆元,可以O(nlogp)计算,也可以用这个方法。

先把∏ni=1g(i) 的逆元计算出来。然后乘一个g(n)就能得到∏ni=1g(i−1) 的逆元。依次递推。线性计算。

至于需要f数组的逆元可以这样算:先把∏ni=1g(i) 的逆元计算出来。然后乘一个∏n−1i=1g(i) ,就能得到g(n)−1然后乘一个g(n)就能得到∏n−1i=1g(i) 的逆元。依次递推。线性计算。

然后总复杂度就变成了O(T∗n√∗logn)

(LateX打到心碎)

树点涂色

我也不知道为什么觉得第一个操作很特别但是就是想不到是lct(或许之前我以为lct只能用于有linkcut操作的题)

第一个操作就是access

然后一个点到根的权值等于到根要经过的虚边个数。

那么access的时候会改变重链的结构,把要断开的那棵子树的权值+1,要接上的那课子树的权值-1,dfs序套个线段树就好了。

第二个操作可以暴力爬(虽然感觉会T可是出题人没卡)。

第三个操作就是区间max。

序列计数

这大概是d1最简单的题了。

看到p=100,n=1e9,脑子里已经想到p3logn矩乘了。先不管有个质数的限制,直接做。这里应该会用到一个数组c[i]表示1~m中%p=i的有多少个,然后考虑至少有一个质数的限制。先筛一遍素数,然后用所有非素数重新做一个c2[i],然后做一遍矩乘。容斥一下就ok了。不知道枚举一个质数的方法是否可行。但是感觉,思考起来比较复杂。

新生舞会

分数规划,先上二分,然后就是裸的费用流了。(好像应该*1e7转成最小割,不过费用流不到6sqwq应该能过吧。)

硬币游戏

这题。。很迷啊。

首先是,不管当前状态是啥,只要没有结束,那后面独立于前面,这些东西可以看成一个状态,设为N。

做了这道题之后我发现,只要你模拟时涉及到无限步的时候,八成是高斯消元。因为只有解方程能把无限解出来。

然后我们假设现在只有两个人,一个A,猜的HHT(kiana!),一个B猜的THH,假如我们现在试图往N后面加一个HHT(相当于确定三个状态),那么A肯定会赢,但是B会不会在A之前赢呢?如果N以T或者TH结尾,B都会比A先赢。

所以这里我们看出 0.125∗P(N)=P(A)+0.75∗P(B)

可以发现,如果将每个人猜的串都试图往N后面加,会得到n个方程,并且,以上面为例,如果B的某个后缀是A的前缀,那么B会在A的方程里产生贡献。这玩意儿就是border(%jcvb),AB串起来求个fail就ok了。

然后高斯消元消出来就行。

啥?你说有n+1个变量?你可以把N当常数然后输出的时候按比例算一下。或者你加一个P(A)+P(B)+...=1也行。

相关分析

首先拆式子

拆到最后是这样(我看过很多人少抵消了两项,不过对于本题来说没什么区别)。(len为询问区间长度)

a=∑xiyi−∑xi∗∑yi/len∑x2i−(∑xi)2/len

然后要维护的四个东西都在里面。

然后5个tag。两个a,b,维护区间加的tag,一个flag表示有没有第三个操作覆盖了,如果有,两个c,d,维护区间覆盖的那两个值。注意别把第三个操作题意读错了。

对于修改操作也是,尽量拆式子。拆完就能维护了。∑xi和∑yi直接维护,∑xiyi需要用∑xi和∑yi , ∑x2i需要∑xi,另外还需要一个sum(i)表示11+22+...+i2的前缀和(直接公式算也ok)。

然后关于两种tag的覆盖关系。区间加是1类,区间覆盖是2类,那么1类push的时候不会影响2类,但是2类push的时候要把1类清空。这个用过线段树维护多个tag的都明白。

啊最后一道题也做完了。(其实这种裸线段树但是tag和要维护的val极其多的题真的恶心。gd有一道题,16个tag 2333)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: