1. 程式人生 > >【胡策篇】題解

【胡策篇】題解

2個 HA 來源 異或 .com rac 方式 合並 tutorial

和泉紗霧與煙花大會


題目來源: UOJ 192 最強跳蚤 (只改了數據範圍)
官方題解: 在這裏哦~(說的很詳細了 我都沒啥好說的了)
題目大意: 求樹上各邊權乘積是完全平方數的路徑數量.

這種從\(n^2\)條路徑中找出滿足xx條件的路徑的條數的題, 我們可以根據常識判斷要用到點分治.
不過這題並沒有用到點分治, 這個一會再說, 我們先來看部分分.

哎呀其實這題好多部分分我都不會寫(捂臉

算法1:

直接乘邊權處理顯然是不行噠, 怕是\(w\leq2\)怕是都要用到高精度了(什麽你說\(w\leq1\), 那還用做嘛←_←)
所以我們考慮每個質因子\(p\), 我們要保證它的出現次數是偶數.

我們就可以預處理每個\(w\)的質因數分解, 然後從每個點開始dfs, 用map存一下每個質數出現的次數, 最後統計一波答案.
這樣應該是時間復雜度\(O(n^2log^2n)\), 空間復雜度\(O(nlogn)\)的, 期望得分30分.(然而由於部分分不一樣大概只能拿到20分, 少的這10分去找驗題人要吧..)

算法2: (窩不會寫)

我們把\(w\)質因數分解,每個出現過的質數離散化一下,可以發現至多出現\(O(nlogn)\)個不同的質數(事實上當\(\frac{w}{n}\)不是很大的時候這個數目是\(O(n)\)的)。
那麽使用bitset維護每個質數的出現次數,再dfs就可以做到\(O(\frac {n^3}{32})\)

了,但是這樣並不能跑出\(n=3000\),事實上我們直接對離散化之後的質數開桶統計就能做到\(O(nlog^2n)\)了,期望得分50分。

算法3:

對於\(w<=100\)的點, 質數的個數不會超過32個, 所以我們就預處理質數然後狀態壓縮一下, 用\(2^{i-1}\)來記錄第\(i\)個質數, 然後從根開始dfs一波, 然後對每一位出現過就xor一下, 如果出現次數是偶數最後xor起來一定是0.

我們最後跑出來的每個點會有一個\(d_i\), 我們可以知道, u xor v=0, 當且僅當u=v, 我們就sort一遍 然後統計相同的就行了.
期望得分20分. 結合算法2期望得分60分.

算法4:

算法3已經很接近正解了. 我們考慮把\(1\sim10^8\)

的每個質數hash成一個long long範圍內的數, 然後像算法3一樣從根一路異或即可. 質因數分解的話我們就預處理出\(10^4\)以內的質數, 然後暴力分解就行了.

時間復雜度大概是\(O(\sqrt w+n\pi(w)+nlogn)\)的, 期望得分100分.


如果能一眼A掉這道題目名稱很長的水題就好了

我覺得題目名說的很對.
題目來源: codeforces938G Shortest Path Queries (挺新的比賽, 我都怕你萌做過..
(就是把數據範圍從20W改成了10W, 求最小改成了求最大, 別的沒了...)
官方題解: 就是找Tutorial啊 (好像是個題解講的都比我好= =)
題目大意: 支持刪邊加邊, 查詢無向圖上兩個點之間異或最長路.

算法1:

\(n,m,q\leq10\)的數據是讓大家解放天性的... 其實出題人並不知道有什麽優美的解決方式... 期望得分10分.

算法2:

任意時刻, 地圖是一棵樹的話很顯然不可能刪邊加邊, 所以就是只有查詢. 而樹上兩點的路徑是唯一的.
所以這個部分分就是... 讓我們異或吧...
期望得分15分. 結合算法1, 期望得分25分.

算法3:

只有查詢的話就是WC2011 XOR了.
隨便找一棵生成樹, 然後用線性基維護所有環即可.
期望得分40分. 結合算法1, 期望得分50分.

算法4:

其實我們發現掃一遍是\(O(n)\)的... 所以我們遇到1,2操作可以暴力重構圖跑..
時間復雜度\(O(q_{1,2}n)\), 期望得分60分.

算法5:

沒有刪除的時候我們可以發現, 每個插入的邊都是環邊, 直接扔到線性基裏處理就完了.
結合算法4, 期望得分70分.

算法6:

沒有插入的時候, 按照套路倒過來做變刪除為插入就行了.
結合算法5, 期望得分80分.

算法7:

都80部分分了寫什麽正解啊.
我們可以一眼看出我們要用動態樹來維護開始時候生成樹的形態, 用線性基動態維護環.
但是好像並不可做吧.

這題可以離線啊! (其實用算法6的時候就發現了OvO)
我們對時間建線段樹, 某個時間段存在某條邊就相當於做區間加, 查詢就相當於另一個標記的單點加.
我們先完成這些區間加和單點加, 然後從頂開始dfs線段樹, 遇到區間加就加上這條邊, 遇到葉子節點就處理所有詢問, 從一個子樹中出來的時候再回滾我們做過的操作(好好想想你過去的所作所為)就行了.
至於維護樹的時候, 可以采用並查集來做到優秀的復雜度, 但是要回滾所以不能做路徑壓縮, 只能按秩合並.

時間復雜度大概是\(O(qlogq(logn+logc))\)的吧, 反正是可以過了.


薇爾莉特·伊芙加登

題目來源:SPOJ DIVCNT2 Counting Divisors(square)
(原題數據範圍實在是撐不住.... 所以還是縮小了...)
題目大意: 求
\[ ans=\sum_{i=1}^nd(\sum_{j=1}^i2j-1) \]
其中\(d(x)\)表示\(x\)的約數個數.

直接按照題意模擬應該是沒分的.
可以很輕易地看出\(\sum_{j=1}^i2j-1=i^2\).
所以要求的其實是\(ans=\sum_{i=1}^nd(i^2)\). (其實這才是原題嘛).
這種東西求前綴和的話, 我會杜教篩!
不過這題似乎並不用杜教篩, 不過復雜度分析的時候用到了和杜教篩同樣的方法.
還是先看看部分分.

算法1:

暴力把\(d\)篩到\(i^2\), 統計答案.
時間復雜度\(O(n^2)\), 期望得分20分.

算法2:

這個平方很煩, 我們看一下能不能用其它式子表示\(d(x^2)\). 我們令
\[ x=\prod_{i}p_i^{k_i} \]
那麽
\[ x^2=\prod_{i}p_i^{2k_i} \]
我們要枚舉\(x^2\)的約數的時候, 可以枚舉\(i\)的約數, 然後對於每個約數
\[ x'=\prod_{i}p_i^{k_i'} \]
我們可以對於每個\(p_i\)都分別乘上\(k_i\), 就成為了\(i^2\)的因子. 所以
\[ d(x^2)=\sum_{d|x}2^{\pi(d)} \]
這個\(2^{\pi(d)}\)是個啥東西呢? 我們可以把它視為\(d\)的每個質因子選0個或者1個之後乘起來得到的\(d\)的因數的個數. 也可以說是\(d\)的無平方因子的個數.
我們還可以驚奇的發現, 無平方因子的\(\mu\)都是-1或1的, 而有平方因子的\(\mu\)都是0, 所以我們可以視為對\(d\)的每個因子\(t\)\(\mu^2\)求個和.
\[ d(x^2)=\sum_{d|x}2^{\pi(d)}=\sum_{d|x}\sum_{t|d}\mu^2(t) \]
這樣暴力枚舉的話大概是\(O(nlnn)\)的吧.
期望得分40分.

算法3:

我們發現上面這個式子可以寫成狄利克雷卷積的形式...
\[ d(x^2)=\sum_{d|x}\sum_{t|d}\mu^2(t)=\sum_{d|x}(\mu^2*1)(d)=((\mu^2*1)*1)(x)=(\mu^2*(1*1))(x)=(\mu^2*d)(x) \]
這玩意顯然是個積性函數, 找個規律線篩即可.
或者還可以化一下式子:
\[ ans=\sum_{i=1}^nd(i^2)=\sum_{i=1}^n(\mu^2*d)(i)=\sum_{i=1}^n\sum_{d|i}\mu^2(d)d(\frac id)=\sum_{d=1}^n\mu^2(d)\sum_{t=1}^{\left \lfloor \frac nd \right \rfloor}d(t) \]
線篩到\(n\)然後分塊求就行了. 時間復雜度\(O(n)\), 期望得分70分.

算法4:

我們看到這個式子
\[ ans=\sum_{d=1}^n\mu^2(d)\sum_{t=1}^{\left \lfloor \frac nd \right \rfloor}d(t) \]
其中這個\(\mu^2\)的前綴和我們可以\(\sqrt n\)的復雜度內算出來.
為什麽呢, 因為有來自bzoj2440的這個式子:
\[ \sum_{i=1}^n\mu^2(i)=\sum_{i=1}^{\left \lfloor \sqrt n \right \rfloor}\mu(i){\left \lfloor \frac n{i^2} \right \rfloor} \]
\[ \sum_{i=1}^nd(i)=\sum_{i=1}^n(1*1)(i)=\sum_{i=1}^n\sum_{d|n}1=\sum_{d=1}^n\left \lfloor \frac nd \right\rfloor \]
所以我們也可以分塊在\(O(\sqrt n)\)的復雜度中求出\(d\)的前綴和.
\(\mu^2\)\(d\)這兩個積性函數我們也可以通過線篩來\(O(n)\)預處理\(O(1)\)查詢.
所以類似於杜教篩的復雜度分析方式(我不知道怎麽推的式子, 不要問我QAQ)
\[ T(n)=O(k+\sum_{i=1}^{\frac nk}\sqrt \frac ni)=O(k+\frac n{\sqrt k}) \]
\(k=n^{\frac 23}\)的時候, 時間復雜度最優為\(O(n^{\frac 23})\).
所以我們線篩預處理出\(n^\frac 23\)以內的\(\mu^2\)\(d\)的值, 然後對\(ans\)分塊搞, 小於\(n^\frac23\)的部分查表, 大的就\(O(\sqrt n)\)暴力搞就行了.
還可以用map或手寫hash map記憶化一下, 速度會有明顯的提升.然而是因為數據原因2333

期望得分100分.

就這些咯, 完結撒花~

【胡策篇】題解