因爲出題人的疏忽,致使T2和T3分別有一個數據造錯,形成了你們沒必要要的麻煩,對此十分抱歉。ubuntu
這裏寫一下三道題的題解:數組
題目連接: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/
題目連接: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/
題目連接: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)。