暑假娛樂賽·題解


由於出題人的疏忽,導致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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM