暑假娱乐赛·题解

由于出题人的疏忽,导致T2和T3分别有一个数据造错,造成了大家不必要的麻烦,对此十分抱歉。

这里写一下三道题的题解:

A--LJJ爱数数

题目链接:https://www.luogu.org/problemnew/show/P4844

题目简述:求出有多少个正整数三元组{a,b,c},满足a,b,c<=n,a,b,c三个数的最大公约数为1,且1/a+1/b=1/c。

数据范围:n<=1e12

tag:本题原型来自中等数学2011年第1期,进行了一番改编。

20分:枚举a,b,O(1)算出c,统计答案

100分:

方法一:

化简后得到(a+b)c=ab,设g=(a,b),A=a/g,B=b/g,则g(A+B)c=ABg^2,即(A+B)c=ABg

由题目已知条件:(a,b,c)=1,即(g,c)=1,g|(A+B)c,故g|(A+B),

设(A+B)/g=AB/c= k ∈ Z,

若k>1,因为A,B互质,所以k|A或k|B,则A+B不能被k整除,矛盾。因此k=1。

故充要条件为:1<=a,b,c<=n,a+b=g^2,c=ab/g^2。

枚举g,则可得A+B=g。用莫比乌斯反演求出一定范围内与g互质的数的个数即可。

写程序的过程中,你会发现,枚举1到sqrt(2n)的g之后,只需枚举g的约数。

所以时间复杂度是O(sqrt(n)log(sqrt(n)))

方法二:(PJY提供的此方法十分巧妙)

可以化简得到:(a+b)c=ab,于是ab-bc-ac+c^2=c^2,所以(a-c)(b-c)=c^2

设a-c=km^2,b-c=kn^2,则c=kmn。

若k>1,(a,b,c)=(km^2+kmn, kn^2+kmn, kmn)≠1,矛盾。故k=1

由此我们知道a-c=m^2,b-c=n^2是完全平方数。

因为(a,b,c)=(m(m+n),n(m+n),mn)=((m+n)*(m,n),mn)=1,所以(m,n)=1

故充要条件为1<=a,b,c<=n,a-c, b-c是完全平方数,c^2=(a-c)(b-c),(a-c,b-c)=1

枚举(a-c),用莫比乌斯反演求出一定范围内与sqrt(a-c)互质的数的个数即可。时间复杂度是O(sqrt(n)log(sqrt(n)))

源码:

方法一:https://paste.ubuntu.com/p/mXF2bvXdy7/

方法二:https://paste.ubuntu.com/p/yn5NddzNjj/ 

 

B--LJJ爱数树

题目链接:https://www.luogu.org/problemnew/show/P4845

题目简述:在一棵n个节点的树上的k个点处放k个摄像头。每个摄像头可以看到与之树上距离<=r的点。

使得被看到的点的w[i]之和最大。

数据范围:k<=n<=1000,w[i]<=1e6

tag:

乱搞做法一:如果一个一个放摄像头,每一次把当前w[i]和最大话,那样例一就过不了

乱搞做法二:如果直接假定关于摄像头个数k的函数f(k)是凸函数,那样例二就过不了(因为这个结论是错误的)

10分:枚举2^n种情况(还可以用位运算优化)。

另外20分(k<=2):做法可能有多种,可以暴力枚举两个点,然后用点分或dsu求每种情况的答案。

40分:暴力dp,定义dp数组f[i][j][k][l],

f[i][j][k1][k2]表示第i个节点的子树处理完毕,子树中放了j个摄像头。

期望被观测,但未被观测的最远的点距离ta为k1;最近的摄像头离ta距离为k2。

该dp复杂度或许是O(n^4)吧,(没实现过不清楚)

100分:接着上述40分的题解讲。

我们在dp的过程中,初始化每个节点有三种状态:什么都没发生;放有一个摄像头;虽没放摄像头,但这个点之后会被观测到。

所以dp的过程中,就决定了每个点是否计入答案。其有用的信息为:子树中离点i最近的摄像头的距离,子树中离点i最远的期望被观测的

点的距离。且信息有用当且仅当距离<=r,因为摄像头的观测范围就是r。

如果两个信息同时存在,那么可以忽略摄像头的信息。

这里证明一下:

设最远的期望被观测的点为a点。最近的摄像头为b点。所以dis(a,b)>r。

之后一定有一个摄像头c点,使得dis(a,c)<=r。那么显然dis(c,i)<dis(b,i)。显然,摄像头b能观测到的在 i 子树外的点,c都能观测到。

所以可以忽略b的信息。

所以理所当然地,可以把dp数组写成f[i][j][k](原先第三维和第四维压缩成一维)

之后的dp,可能细节有些繁琐。导致标程可读性差。所以题解里就不阐述了。

这样还不够,因为n<=1000。

我们还需要证明一下:当k*r>=n时,所有的点都能够被观测到。

随便选一个点提根。取深度最深的点,如果深度<=r,直接选择根节点放摄像头。

若深度dep>r,选择与该点距离r的祖先,选择该祖先放摄像头,这样相当于花费一个摄像头砍去了点数>=r的一个子树。

故容易证明k*r>=n时,所有点都能观测到。

所以,k*r<n时,枚举点i,依次把它的儿子所代表的子树合并起来,复杂度是min(k,size[a])*min(k,size[b])*r。

总复杂度可以证明是n*k*r<n^2。(不详细讲证明了)

源码:

标程:https://paste.ubuntu.com/p/gdFgv42mzf/

翠竹叶飞的代码:https://paste.ubuntu.com/p/4jJyCCyddq/

 

C--LJJ爱数书

题目链接:https://www.luogu.org/problemnew/show/P4846

题目简述:

一个序列A,每次操作可以使一段连续的区间加1或减1并对K取模,定义F(A,K)表示最少的操作次数使得序列的所有元素都变为0。

输入长度为n的序列A,m次询问F(A[x][y],K)的值。

数据范围:

n<=200000, m<=100000, k<=1e9

tag:

唯一一道数据结构题,所以思路不是那么难。只要你会50分,就可以轻松优化到100分。

10分:搜索+剪枝

30分:先考虑单组询问求F(A,K)。为了方便之后处理,首尾加 0 。

设长度变为N=n+2

我们先考虑如果操作中每次加一、减一后不取模。若A[i]∈Z(可能是负数)。

先对A差分 -> 设B[i]=A[i]-A[i-1](对于1<i<=n),显然B[2]+B[3]+...+B[N]=0

每次操作等同于,B[i]加一,B[j]减一( 1<i,j<=N ),目标是将所有的B[i]变为0。

若未达到目标,因为所有的B[i]之和为0。一定存在B[i]>0,B[j]<0。

所以一定存在一次操作,使得B[i]的绝对值的和减2。

由此我们知道,此时最小操作次数是[abs(B[2])+abs(B[3])+...+abs(B[N])] / 2。(此处abs表示绝对值)

现在题中操作为每次加一、减一后对K取模。所以等同于,先将A数组的某些元素加或减K的倍数。

等同于我们先对差分数组B中某些元素加或减K(根据之前最小操作次数的公式,显然加减范围不会超过K),并维持B[2]+B[3]+...+B[N]=0。

求这样的情况下,[abs(B[2])+abs(B[3])+...+abs(B[N])]/2 的最小值。

容易实现单次询问O(n^2) dp。

50分:接着30分的题解讲,我们要对差分数组的某些数值加K或减K,并维持B[2]+B[3]+...+B[n]=0。

设在S个位置加K,在S个位置减K。(这2S个位置不重复)

显然,我们只会在小于0的位置加K,在大于0的位置减K。所以前者和后者一定不重复。

对于小于0的数 (-a),对其加K可以使代价减少 (2a-K)。

对于大于0的数(a),对其减K可以使代价减少 (2a-K)。

所以,对要加K和要减K的位置,选2a-K前S大的位置,(a是其绝对值)

容易做到单次询问O(n),总复杂度O(mn)。

100分:接着50分的题解讲,显然,我们可以二分这个K,求区间第K大和前K大和即可。(这里不再赘述)

使用主席树或划分树可做到复杂度O(mlog^2n)。

 源码:https://paste.ubuntu.com/p/mYvBWMJ5vx/

posted @ 2018-08-03 20:02  I_m_Eden  阅读(3274)  评论(5编辑  收藏  举报