[51nod]演算法馬拉松18 總結

TA201314發表於2016-09-24

第一次打馬拉松。。
a
一看題。。什麼鬼。。
n=4竟然是無解,第一個點給了一個n=5的,好像是構造的挺有規律的樣子。。
那就偶數無解,奇數照著他的構造方法寫一發吧。。
怎麼a了?不管了。。

既然結束了還是要回來好好想一下是什麼情況的。
偶數肯定是無解的,因為一共有n(n1)2

n(n-1)\over 2
條邊,那麼每種顏色的邊出現次數相等的話,就意味著每條邊應該出現n12
n-1\over 2
次,那麼就要求n1mod20
n-1\mod 2\equiv 0
,所以n只能是奇數。
那麼我們不妨把節點和顏色編號改為[0,n),然後令(i,j)的顏色是i+j mod n.
這樣對於任意一個三元環(i,j,k)(i<j<k
i<j<k
),它的邊的顏色就是(i+j,j+k,i+k)。二者之間其實是可以一一對映的。如果邊的顏色是(a,b,c),那麼三元環就是(a+bc2,a+cb2,b+ca2
{a+b-c\over 2},{a+c-b\over 2},{b+c-a\over 2}
),而既然n是奇數,那麼2就是有逆元的。
b
一開始沒有考慮清楚邊界情況,以為直接從n=0開始dp,前面的都塞滿0就可以了,但是這樣的話n=2的時候10就會是一個非法狀態。所以說要從n=2或3開始dp才行。
c
顯然零點有一個π
\pi
的週期,然後我猜它在(0,π)
(0,\pi)
是單調的,二分了一個零點。
結果一直過不了樣例,調了半天發現把一個double寫成int了。。交上去發現a了。。

結束了之後來考慮一下這是什麼情況。。
於是又學了一遍三角函式。。最後發現原來這麼大的式子根本毫無卵用。

k=1w(Asin(x+k)k+sin(k)+Bcos(x+k)k+cos(k))=k=1w(Ak+sin(k)(cosksinx+sinkcosx)+Bk+cos(k)(coskcosxsinksinx))=asinx+bcosx=αsin(x+β)
\sum_{k=1}^w({Asin(x+k)\over k+sin(k)}+{Bcos(x+k)\over k+cos(k)})\\=\sum_{k=1}^w({A\over k+sin(k)}(cosksinx+sinkcosx)+{B\over k+cos(k)}(coskcosx-sinksinx))\\=asinx+bcosx\\=\alpha sin(x+\beta)
也就是由輔助角公式的一個簡單推論:sin(x)的線性和還是sin(x)。
d
顯然答案的式子應該這麼化:xsubtree(v),vson(u)(size(u)size(v))bit[depth[x]depth[u]]
\sum_{x\in subtree(v),v\in son(u)}(size(u)-size(v))bit[depth[x]-depth[u]]

我們單獨考慮每一位2k
2^k
,顯然如果在mod2k+1
\mod 2^{k+1}
意義下運算這一位是不會變的。如果這一位是1的話,就意味著xa[2k,2k+1)
x-a\in [2^k,2^{k+1})
。那麼就相當於是子樹查詢權值在一個範圍裡的數的個數。
可以dfs序+主席樹,但是常數太大T了。。後來發現直接在dfs的時候+bit就很好寫。。
時間複雜度O(nlog22n)
O(n\log_2^2n)

e
對於每一個g(i)
g(i)
,列舉它的約數j,f(ij)
f({i\over j})
會被貢獻h(j)次。
j=px11px22...
j=p_1^{x_1}p_2^{x_2}...
,則h(j)=o(k+xo1k1)
h(j)=\prod_{o}\binom{k+x_o-1}{k-1}
.
這樣k雖然看起來很大,但是沒啥用直接模109+7
10^9+7
就行。
先篩出每個數的最小質因子,然後h,g都可以暴力求,時間複雜度O(nlogn)
O(n\log n)
.
f
考慮f(i,k)表示X部1~i個點匹配了k個,最大的Y部的節點是多少。
轉移就是
f(i,k)=min{f(i1,k)li,f(i1,k1)<lif(i1,k1)+1,f(i1,k1)[li,ri)}
f(i,k)=min\{ \\f(i-1,k)\\l_i,f(i-1,k-1)<l_i\\f(i-1,k-1)+1,f(i-1,k-1)\in[l_i,r_i) \\ \}

那麼考慮同一個i,對於k來說f顯然是單增的。因為假如有f(i,k)≤f(i,k-1),那麼考慮在f(i,k)的最優方案中,前k-1條匹配邊一定 < f(i,k),那麼就意味著f(i,k-1) < f(i,k),就產生矛盾了。
也就是說其實f(i,k)的轉移是如果f(i1,k1)[li,ri)
f(i-1,k-1)\in[l_i,r_i)
,就一定有f(i,k)=f(i1,k1)+1
f(i,k)=f(i-1,k-1)+1
,因為f(i1,k1)+1f(i1,k)
f(i-1,k-1)+1\le f(i-1,k)
;否則如果f(i1,k1)<li
f(i-1,k-1)<l_i
&&f(i1,k)li
f(i-1,k)\ge l_i
,就一定有f(i,k)=li
f(i,k)=l_i
.
那麼就相當於是區間+1,單點修改,把一個數移到從一個地方移到另一個地方。就用splay/fhq treap維護一下就可以了。
很久沒寫splay了。。結果找前驅/後繼的時候忘了pushdown調了一個小時。。
時間複雜度O(nlogn)
O(n\log n)
,結果跑了2s+…
總結:
①dp的時候一定要考慮好邊界情況。
②一定要想清楚變數的型別int/long long/double.
③寫程式碼的時候一定要考慮清楚。
④sin(x)的線性和還是sin(x).
⑤遍歷樹的時候一定要記得下傳標記!

相關文章