JZOJ5787 軌道
題目大意
給出 \(n\),\(m\)。
需要構造一個長度為 \(n\) 的正整數序列 \(A\),其中 \(A_i \in [1,m]\)。
給出一個正整數 \(K\)。你的序列需要使的存在一個正整數 \(V\),使得 \(V \cdot K = \prod A_i\) 且 \(V\) 與 \(K\) 互質。
求出構造方案數。
其中 \(n \leq 30001, m \leq 10^9, K \leq 10^7\)。
解題思路
考慮 DP
設 \(dp(i,j)\) 表示構造到 \(i\) 位,使得 \(\prod A_i = j\) 的方案數。
這樣顯然開不下,但是發現其實我們只關心 \(\gcd(j,K)\)。
顯然 \(\gcd(j,K)\) 是 \(K\) 的因數,我們將因數全部預處理出來,從小到大排列,記為數列 \(a\),這不會太多,數量 \(at \leq 1000\)。
同時記 \(mp(i)\) 表示 \(i\) 在 \(K\) 的因數中的排名。
所以我們將 \(dp(i,j)\) 含義改成:構造到 \(i\) 位,使得 \(\gcd(\prod A_i,K) = a[j]\) 的方案數。
那麼我們可以推出狀態轉移方程:
考慮如何實現轉移,我們可以預處理出 \(a(j)\) 的所有因數,這將耗費 \(O(at^2) \leq 10^6\) 的時間。
經過預處理,轉移的總時間消耗為 \(O(n\sum \sigma_0(a(i))) \leq 2*10^4 n \leq 6*10^8\),實際上這個數字會更加的小,其中 \(\sigma_0\) 表示因數個數。
我們解決了轉移問題,接下來考慮如何求出 \(dp(1,j)\)。
考慮其含義,即數 \(x \in [1,m]\) 使得 \(\gcd(x,K) = a(j)\) 並且 \(\gcd(\frac{x}{a(j)},K) = 1\) 的個數。
直接列舉不可行,考慮進行一步轉化,第二個條件等價於:
第三個條件可以推出條件二,故關鍵在於條件三。
令 \(y \in [1,\dfrac{m}{a(j)}]\)。
即求 \(y\) 與 \(K\) 互質的個數,使用容斥原理。
即\(1\) 的倍數,減去 \(2\) 的倍數,減去 \(3\) 的倍數,加上 \(6\) 的倍數等等,的小學問題。
更具體的其容斥係數即為莫比烏斯函式 \(\mu\),不難理解。
更嚴謹的,使用莫比烏斯反演:
\[f(i) = \sum_{j}^{N} [\gcd(j,K)=i] \\ F(i) = \sum_{i|j} f(j) = \sum_{j}^{N} [i|\gcd(j,K)] = \lfloor \frac{N}{i} \rfloor \]其中要求 \(i|K\)。
根據莫比烏斯反演,所求 \(f(1)\) 即為:
\[f(1) = \sum_{i|K} \mu(i) F(i) \]
線性篩出莫比烏斯函式 \(O(K) \leq 10^7\),預處理 \(O(at^2) \leq 10^6\)。
至此,我們解決了這個問題。
參考程式碼