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