【胡策篇】题解

和泉纱雾与烟花大会



题目来源: UOJ 192 最强跳蚤 (只改了数据范围)
官方题解: 在这里哦~(说的很详细了 我都没啥好说的了)
题目大意: 求树上各边权乘积是完全平方数的路径数量.

这种从\(n^2\)条路径中找出满足xx条件的路径的条数的题, 我们可以根据常识判断要用到点分治.
不过这题并没有用到点分治, 这个一会再说, 我们先来看部分分.

哎呀其实这题好多部分分我都不会写(捂脸

算法1:

直接乘边权处理显然是不行哒, 怕是\(w\leq2\)怕是都要用到高精度了(什么你说\(w\leq1\), 那还用做嘛←_←)
所以我们考虑每个质因子\(p\), 我们要保证它的出现次数是偶数.

我们就可以预处理每个\(w\)的质因数分解, 然后从每个点开始dfs, 用map存一下每个质数出现的次数, 最后统计一波答案.
这样应该是时间复杂度\(O(n^2log^2n)\), 空间复杂度\(O(nlogn)\)的, 期望得分30分.(然而由于部分分不一样大概只能拿到20分, 少的这10分去找验题人要吧..)

算法2: (窝不会写)

我们把\(w\)质因数分解,每个出现过的质数离散化一下,可以发现至多出现\(O(nlogn)\)个不同的质数(事实上当\(\frac{w}{n}\)不是很大的时候这个数目是\(O(n)\)的)。
那么使用bitset维护每个质数的出现次数,再dfs就可以做到\(O(\frac {n^3}{32})\)了,但是这样并不能跑出\(n=3000\),事实上我们直接对离散化之后的质数开桶统计就能做到\(O(nlog^2n)\)了,期望得分50分。

算法3:

对于\(w<=100\)的点, 质数的个数不会超过32个, 所以我们就预处理质数然后状态压缩一下, 用\(2^{i-1}\)来记录第\(i\)个质数, 然后从根开始dfs一波, 然后对每一位出现过就xor一下, 如果出现次数是偶数最后xor起来一定是0.

我们最后跑出来的每个点会有一个\(d_i\), 我们可以知道, u xor v=0, 当且仅当u=v, 我们就sort一遍 然后统计相同的就行了.
期望得分20分. 结合算法2期望得分60分.

算法4:

算法3已经很接近正解了. 我们考虑把\(1\sim10^8\)的每个质数hash成一个long long范围内的数, 然后像算法3一样从根一路异或即可. 质因数分解的话我们就预处理出\(10^4\)以内的质数, 然后暴力分解就行了.

时间复杂度大概是\(O(\sqrt w+n\pi(w)+nlogn)\)的, 期望得分100分.


如果能一眼A掉这道题目名称很长的水题就好了

我觉得题目名说的很对.
题目来源: codeforces938G Shortest Path Queries (挺新的比赛, 我都怕你萌做过..
(就是把数据范围从20W改成了10W, 求最小改成了求最大, 别的没了...)
官方题解: 就是找Tutorial啊 (好像是个题解讲的都比我好= =)
题目大意: 支持删边加边, 查询无向图上两个点之间异或最长路.

算法1:

\(n,m,q\leq10\)的数据是让大家解放天性的... 其实出题人并不知道有什么优美的解决方式... 期望得分10分.

算法2:

任意时刻, 地图是一棵树的话很显然不可能删边加边, 所以就是只有查询. 而树上两点的路径是唯一的.
所以这个部分分就是... 让我们异或吧...
期望得分15分. 结合算法1, 期望得分25分.

算法3:

只有查询的话就是WC2011 XOR了.
随便找一棵生成树, 然后用线性基维护所有环即可.
期望得分40分. 结合算法1, 期望得分50分.

算法4:

其实我们发现扫一遍是\(O(n)\)的... 所以我们遇到1,2操作可以暴力重构图跑..
时间复杂度\(O(q_{1,2}n)\), 期望得分60分.

算法5:

没有删除的时候我们可以发现, 每个插入的边都是环边, 直接扔到线性基里处理就完了.
结合算法4, 期望得分70分.

算法6:

没有插入的时候, 按照套路倒过来做变删除为插入就行了.
结合算法5, 期望得分80分.

算法7:

都80部分分了写什么正解啊.
我们可以一眼看出我们要用动态树来维护开始时候生成树的形态, 用线性基动态维护环.
但是好像并不可做吧.

这题可以离线啊! (其实用算法6的时候就发现了OvO)
我们对时间建线段树, 某个时间段存在某条边就相当于做区间加, 查询就相当于另一个标记的单点加.
我们先完成这些区间加和单点加, 然后从顶开始dfs线段树, 遇到区间加就加上这条边, 遇到叶子节点就处理所有询问, 从一个子树中出来的时候再回滚我们做过的操作(好好想想你过去的所作所为)就行了.
至于维护树的时候, 可以采用并查集来做到优秀的复杂度, 但是要回滚所以不能做路径压缩, 只能按秩合并.

时间复杂度大概是\(O(qlogq(logn+logc))\)的吧, 反正是可以过了.


薇尔莉特·伊芙加登

题目来源:SPOJ DIVCNT2 Counting Divisors(square)
(原题数据范围实在是撑不住.... 所以还是缩小了...)
题目大意: 求
\[
ans=\sum_{i=1}^nd(\sum_{j=1}^i2j-1)
\]
其中\(d(x)\)表示\(x\)的约数个数.

直接按照题意模拟应该是没分的.
可以很轻易地看出\(\sum_{j=1}^i2j-1=i^2\).
所以要求的其实是\(ans=\sum_{i=1}^nd(i^2)\). (其实这才是原题嘛).
这种东西求前缀和的话, 我会杜教筛!
不过这题似乎并不用杜教筛, 不过复杂度分析的时候用到了和杜教筛同样的方法.
还是先看看部分分.

算法1:

暴力把\(d\)筛到\(i^2\), 统计答案.
时间复杂度\(O(n^2)\), 期望得分20分.

算法2:

这个平方很烦, 我们看一下能不能用其它式子表示\(d(x^2)\). 我们令
\[
x=\prod_{i}p_i^{k_i}
\]
那么
\[
x^2=\prod_{i}p_i^{2k_i}
\]
我们要枚举\(x^2\)的约数的时候, 可以枚举\(i\)的约数, 然后对于每个约数
\[
x'=\prod_{i}p_i^{k_i'}
\]
我们可以对于每个\(p_i\)都分别乘上\(k_i\), 就成为了\(i^2\)的因子. 所以
\[
d(x^2)=\sum_{d|x}2^{\pi(d)}
\]
这个\(2^{\pi(d)}\)是个啥东西呢? 我们可以把它视为\(d\)的每个质因子选0个或者1个之后乘起来得到的\(d\)的因数的个数. 也可以说是\(d\)的无平方因子的个数.
我们还可以惊奇的发现, 无平方因子的\(\mu\)都是-1或1的, 而有平方因子的\(\mu\)都是0, 所以我们可以视为对\(d\)的每个因子\(t\)的\(\mu^2\)求个和.
\[
d(x^2)=\sum_{d|x}2^{\pi(d)}=\sum_{d|x}\sum_{t|d}\mu^2(t)
\]
这样暴力枚举的话大概是\(O(nlnn)\)的吧.
期望得分40分.

算法3:

我们发现上面这个式子可以写成狄利克雷卷积的形式...
\[
d(x^2)=\sum_{d|x}\sum_{t|d}\mu^2(t)=\sum_{d|x}(\mu^2*1)(d)=((\mu^2*1)*1)(x)=(\mu^2*(1*1))(x)=(\mu^2*d)(x)
\]
这玩意显然是个积性函数, 找个规律线筛即可.
或者还可以化一下式子:
\[
ans=\sum_{i=1}^nd(i^2)=\sum_{i=1}^n(\mu^2*d)(i)=\sum_{i=1}^n\sum_{d|i}\mu^2(d)d(\frac id)=\sum_{d=1}^n\mu^2(d)\sum_{t=1}^{\left \lfloor \frac nd \right \rfloor}d(t)
\]
线筛到\(n\)然后分块求就行了. 时间复杂度\(O(n)\), 期望得分70分.

算法4:

我们看到这个式子
\[
ans=\sum_{d=1}^n\mu^2(d)\sum_{t=1}^{\left \lfloor \frac nd \right \rfloor}d(t)
\]
其中这个\(\mu^2\)的前缀和我们可以\(\sqrt n\)的复杂度内算出来.
为什么呢, 因为有来自bzoj2440的这个式子:
\[
\sum_{i=1}^n\mu^2(i)=\sum_{i=1}^{\left \lfloor \sqrt n \right \rfloor}\mu(i){\left \lfloor \frac n{i^2} \right \rfloor}
\]
\[
\sum_{i=1}^nd(i)=\sum_{i=1}^n(1*1)(i)=\sum_{i=1}^n\sum_{d|n}1=\sum_{d=1}^n\left \lfloor \frac nd \right\rfloor
\]
所以我们也可以分块在\(O(\sqrt n)\)的复杂度中求出\(d\)的前缀和.
而\(\mu^2\)和\(d\)这两个积性函数我们也可以通过线筛来\(O(n)\)预处理\(O(1)\)查询.
所以类似于杜教筛的复杂度分析方式(我不知道怎么推的式子, 不要问我QAQ)
\[
T(n)=O(k+\sum_{i=1}^{\frac nk}\sqrt \frac ni)=O(k+\frac n{\sqrt k})
\]
当\(k=n^{\frac 23}\)的时候, 时间复杂度最优为\(O(n^{\frac 23})\).
所以我们线筛预处理出\(n^\frac 23\)以内的\(\mu^2\)和\(d\)的值, 然后对\(ans\)分块搞, 小于\(n^\frac23\)的部分查表, 大的就\(O(\sqrt n)\)暴力搞就行了.
还可以用map或手写hash map记忆化一下, 速度会有明显的提升.然而是因为数据原因2333

期望得分100分.

就这些咯, 完结撒花~

原文地址:https://www.cnblogs.com/enzymii/p/8630406.html

时间: 2024-10-13 10:56:45

【胡策篇】题解的相关文章

【胡策篇】题目

和泉纱雾与烟花大会(eromanga) 时间限制: 2s 空间限制: 256MB 题目背景 和泉纱雾是个灰常可爱的女孩子. 你永远不知道有多少恶心的死宅看到了纱雾之后, 便吵着换老婆, 正如三个月前和三个月后的他们一样. 作为一个家里蹲, 她看到了电视上转播的烟花大会, 于是特别想去看. 他的哥哥和泉正宗决定抓住这大好的机会带她去看烟花. 这一对兄妹有说有笑的来到了烟花大会的会场. (德国骨科了解一下←_←) 题目描述 烟花大会的会场非常大, 一共有\(n\)个观景点. 这\(n\)个观景点通过

弱省胡策系列简要题解

现在不是非常爽,感觉智商掉没了,就整理一下最近弱省胡策的题目吧. 其实题目质量还是很高的. 如果实在看不懂官方题解,说不定这里bb的能给您一些帮助呢? [弱省胡策]Round #0 A 20%数据,O(n4)傻逼dp. 40%数据,O(n3)傻逼dp. 100%数据,令f(x1,y1,x2,y2)表示从(x1,y1)走到(x2,y2)的路径条数.于是所有路径就是f(1,2,n?1,m)×f(2,1,n,m?1).然而两条路径可能在中间的某个点相交,我们找出最早的交点,并在这个交点互换两条路径的后

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

校内胡策(唯一一个想出来的)

2 第一题 (third.cpp/c/pas) 题目描述 小 R 最近沉迷于一个叫做 Slay.one 的游戏. 在这个游戏中,每一局有若干人参加,最终会产生一个优胜者.优胜者会获得 一个成就点. 现在小 R 已经利用某种手段得知了每场游戏有哪些人参加.假设所有人最初成 就点都是 0 ,小 R 想要知道所有游戏结束之后成就点最多的人至少有多少成就点. 校内胡策(唯一一个想出来的) 原文地址:https://www.cnblogs.com/Lance1ot/p/9445468.html

【题解】[CH弱省胡策R2]TATT

本蒟蒻第一道\(K-D-Tree\)维护\(dp\) Question 题目大意:求一条路径,使得其四个维度单调不降. 先排序消掉一维再说. 对于每一个点,初始的时候绝对长度是1啊.于是,先赋值一个1,对于每一个点. 设计\(dp\)数组 \[f[i]=max_{f[j]}(a[j]<=a[i],b[j]<=b[i],c[j]<=c[i],d[j]<=d[i])\] 那问题就转为,对于每一个点,如何求出在它之前的最大\(f[i]\)值. 发现问题类似于三维偏序,正好\(K-D-Tr

山西胡策 #6

A. 题意:求去掉d物品后容量为e最大背包.每个物品有三种属性,权值.容量.数量. #include <bits/stdc++.h> using namespace std; const int V=1000, N=1005; void zop(int *d, int w, int v) { for(int i=V; i>=v; --i) d[i]=max(d[i], d[i-v]+w); } void cmp(int *d, int w, int v) { for(int i=v; i

山西胡策 #7

A. B. C. 题意:给出(i, j)之类的约束表示要j必须先i,问1尽量靠前.2尽量靠前.3尽量靠前以此类推的最优方案,或输出无解. #include <bits/stdc++.h> using namespace std; const int N=100005; int cnt, ihead[N], in[N], ans[N], tot, n, m; struct E { int next, to; }e[N]; void add(int x, int y) { e[++cnt]=(E)

我的第一篇题解——A+B Problem

背景 "任何一个伟大的思想,都有一个微不足道的开始."   --A+B Problem 题目描述 输入两个整数a,b,输出它们的和(|a|,|b|<=10^9). 输入输出格式 输入格式: 两个整数以空格分开 输出格式: 一个数,即两数之和 输入输出样例 输入样例#1: 20 30 输出样例#1: 50 思路 这是一道简单的入门题,放在这里是为了攒RP(顺便调试一下字体),直接上标程 标程 1 #include<cstdio> 2 /* 3 #include<i

STOI补番队胡策

#1 第一轮是我出的. 比赛情况: #1 NanoApe 300 (完美AK) #2 && #3 swm_sxt / ccz  200 A.candy 这道题就是个nim游戏, 我们知道当且仅当选出的各堆糖果的异或和为0时,先手必败. 这样问题转化为从N个数中选1一些数使得他们的异或和为0的方案数. 30%,O(2^N) DFS. 假如只有询问, 那么可以直接用类似01背包的dp解决. for i = 1 ~ 1024 dp(i, x) += dp(i-1, x^w_i); dp(i, x