博客觀賞效果更佳:
cnblogs
github
算法講解
(本篇文章假設您學過莫比烏斯反演 (〃‘▽’〃)
我們知道莫比烏斯函數有一個性質: ∑ d ∣ n μ ( d ) = [ n = 1 ] \sum\limits_{d|n} \mu(d)=[n=1] d ∣ n ∑ μ ( d ) = [ n = 1 ]
根據這條性質,我們寫出一個類似篩的東西:一個數組,初始都是 0 0 0 。 第 i i i 輪,將 i i i 的倍數都加上 μ ( i ) \mu(i) μ ( i ) 。
n n n 輪之後,顯然只有第一個位置還剩一個 1 1 1 ,其它都變成了 0 0 0 。好好理解下這個表,然後往下看。
那麼,假設現在我們要求 n = 1 n=1 n = 1 時的答案,但是我們方便求的只有 n n n 的倍數的答案和,如何轉化捏 (⊙.⊙)
我們設 f ( x ) f(x) f ( x ) 表示 n n n 恰好爲 x x x 的答案,F ( x ) F(x) F ( x ) 表示 n n n 爲 x x x 的倍數的答案和,即 ∑ d ∣ n f ( n ) \sum\limits_{d|n} f(n) d ∣ n ∑ f ( n ) 。
考慮 ∑ i = 1 n μ ( i ) F ( i ) \sum\limits_{i=1}^{n} \mu(i)F(i) i = 1 ∑ n μ ( i ) F ( i ) ,
它 = ∑ i = 1 n ∑ i ∣ j μ ( i ) f ( j ) =\sum\limits_{i=1}^{n}\sum\limits_{i|j} \mu(i)f(j) = i = 1 ∑ n i ∣ j ∑ μ ( i ) f ( j )
考慮每個 f ( i ) f(i) f ( i ) 被算了多少次,變爲:
∑ j = 1 n f ( j ) ∑ i ∣ j μ ( i ) = ∑ j = 1 n f ( j ) [ j = 1 ] = f ( 1 ) \sum\limits_{j=1}^{n} f(j) \sum\limits_{i|j} \mu(i)=\sum\limits_{j=1}^{n} f(j) [j=1]=f(1) j = 1 ∑ n f ( j ) i ∣ j ∑ μ ( i ) = j = 1 ∑ n f ( j ) [ j = 1 ] = f ( 1 )
f ( 1 ) f(1) f ( 1 ) 不就是我們要求的,n n n 恰好爲 1 1 1 的方案嗎(✪ω✪)
所以,莫比烏斯容斥的解題步驟:
轉化成 n = 1 n=1 n = 1 的方案(一般這步比較考思維)
求 n n n 的倍數的方案和
說這些有點抽象,還是做點題☆daze~
起飛~
T1. CF 439E
給定 q q q 個詢問,每次給定 n , k n,k n , k ,問有多少種方法,把 n n n 分成 k k k 個數相加,並且 所有數 的 gcd \gcd g cd 爲 1 1 1 (即:允許有部分的 gcd \gcd g cd 不爲 1 1 1 ,比如 n = 20 , k = 3 n=20,k=3 n = 2 0 , k = 3 時,{ 2 , 3 , 15 } \{2,3,15\} { 2 , 3 , 1 5 } 是合法的一組拆分)
q , n ≤ 1 0 5 , k ≤ n q,n\le 10^5,k\le n q , n ≤ 1 0 5 , k ≤ n
題解
如何轉化成上面的 “n = 1 n=1 n = 1 的方案數” 呢
設 f ( i ) f(i) f ( i ) 表示:k k k 個數的 gcd = i \gcd=i g cd= i 的方案數,F ( i ) F(i) F ( i ) 表示:k k k 個數的 gcd \gcd g cd 爲 i i i 的倍數的方案數(即:k k k 個數都是 i i i 的倍數的方案數)
F ( i ) F(i) F ( i ) 好求。顯然,此時 i i i 是 n n n 的因數(k k k 個數都是 i i i 的倍數,所以它們加起來, n n n 也是 i i i 的倍數)。如果不是,那麼 F ( i ) = 0 F(i)=0 F ( i ) = 0
然後所有數都是 i i i 的倍數的劃分方案,我們可以把 i i i 個數併成一塊,然後有 n / i n/i n / i 個塊,任意劃分成 k k k 個部分,求方案數。然後我們在 n / i n/i n / i 個塊中間插入 n / i − 1 n/i-1 n / i − 1 個隔板,選擇 k − 1 k-1 k − 1 個,就能把 n n n 個數分成 k k k 個部分,每個部分都是 i i i 的倍數了。這樣方案數是 F ( i ) = C n / i − 1 k − 1 F(i)=C_{n/i-1}^{k-1} F ( i ) = C n / i − 1 k − 1 。預處理階乘和階乘逆元,這個 O ( 1 ) O(1) O ( 1 ) 算。
然後根據莫比烏斯容斥的式子,f ( 1 ) = ∑ i = 1 n F ( i ) f(1)=\sum\limits_{i=1}^{n} F(i) f ( 1 ) = i = 1 ∑ n F ( i ) 。然後在這題中要變下型 (看上面),因爲 i ∣ n i|n i ∣ n 時,F ( i ) F(i) F ( i ) 才能按照上面的方法算,否則 F ( i ) = 0 F(i)=0 F ( i ) = 0 。於是, f ( 1 ) = ∑ i ∣ n F ( i ) f(1)=\sum\limits_{i|n} F(i) f ( 1 ) = i ∣ n ∑ F ( i )
然後這個枚舉因數是 O ( n ) O(\sqrt{n}) O ( n ) 的。總的複雜度 O ( q n ) O(q\sqrt{n}) O ( q n ) ,能過。
代碼 (篇幅問題,我就不放主頁了(*▽ *))(代碼看不懂的右下角聯繫我,或者在代碼那邊的評論區留言~~❤)
T2. CF 900D
同樣是求劃分的問題。相當於在 T 1 T1 T 1 的基礎上:
去掉 k k k 的限制
一組詢問,範圍改成 n ≤ 1 0 9 n\le 10^9 n ≤ 1 0 9 ,答案模 1 0 9 + 7 10^9+7 1 0 9 + 7
給定了參數 y y y ,劃分完所有數的 gcd = y \gcd=y g cd= y (而不是等於 1 1 1 )
題解
所有數 gcd = y \gcd=y g cd= y ,相當於所有數除以 y y y 之後 gcd = 1 \gcd=1 g cd= 1 。
然後沒有了 k k k 的限制,相當於所有的隔板隨便選/不選。這咋整捏 ⊙(・◇・)?
假設有 n n n 個隔板,答案爲 2 n 2^{n} 2 n 。然後,n n n 個數不限個數劃分,每個數都是 y y y 的倍數,方案數就是 2 n / y − 1 2^{n/y-1} 2 n / y − 1 。
然後要注意的是,n ≤ 1 0 9 n\le 10^9 n ≤ 1 0 9 ,只有一部分 μ \mu μ 可以篩出來,超過範圍的就只好暴力算了。
這個時間複雜度有點玄學…但還是能過的 φ(>ω<*)
代碼
T3. CF1036F
T T T 組詢問,每次詢問 [ 2 , n ] [2,n] [ 2 , n ] 中有多少好數。一個數 x x x 是“好數”,那麼不存在任何一個 k k k 使得 x k \sqrt[k]{x} k x 是整數。
T ≤ 1 0 5 , x ≤ 1 0 18 T\le 10^5,x\le 10^{18} T ≤ 1 0 5 , x ≤ 1 0 1 8 。
題解
一個數是“好數”,那麼它分解質因數後,所有指數的 gcd = 1 \gcd=1 g cd= 1
然後我們考慮所有指數的 gcd \gcd g cd 是 k k k 的倍數怎麼算。很顯然,這個方案數就是 ⌊ x k ⌋ \lfloor \sqrt[k]{x} \rfloor ⌊ k x ⌋ 。
然後 k k k 大概枚舉到 60 , 70 60,70 6 0 , 7 0 就夠了。
然後卡億點點 常數就過了 o(╥﹏╥)o
代碼
結語
如果您認真的看完並理解了我上面的瞎扯…
恭喜您!學會了莫比烏斯反演!φ(>ω<*)
完結撒花花~~~