暑假娱乐赛·题解

因为出题人的疏忽,致使T2和T3分别有一个数据造错,形成了你们没必要要的麻烦,对此十分抱歉。ubuntu

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

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期,进行了一番改编。get

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=ABgast

由题目已知条件:(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

咱们先考虑若是操做中每次加1、减一后不取模。若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表示绝对值)

如今题中操做为每次加1、减一后对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/