Frogs - HDU5514
Frogs - HDU5514
icpc沈陽2015的題目。
容斥原理和數論的應用。
題目大意為給你一個數組 a[i]a[i]a[i](a[i]a[i]a[i] 即為第 iii 只青蛙的步長) 和若干格子編號為 000 到 m?1m - 1m?1,對于任意的正整數 k,ik, ik,i,編號為 k?a[i]modmk * a[i] \mod mk?a[i]modm 的格子會被占用,問所有被占用的格子的編號之和。
首先對于一個 a[i]a[i]a[i],顯然所有編號為 gcd?(a[i],m)\gcd(a[i], m)gcd(a[i],m) 的倍數的格子會被占用,拋棄掉之前的 a[i]a[i]a[i] ,直接將 gcd?(a[i],m)\gcd(a[i], m)gcd(a[i],m) 設為新的 a[i]a[i]a[i],這樣的話,我們記 a[i]a[i]a[i] 的倍數組成的集合為 AiA_iAi?,那么最終答案為 S(A1∪A2∪?∪An)S(A_1 \cup A_2 \cup \dots \cup A_n)S(A1?∪A2?∪?∪An?),其中 S(A)S(A)S(A) 為集合 AAA 中所有元素的和。
這個東西顯然可以用容斥做,我們記集合 {A1,A2,…,An}\{A_1, A_2, \dots, A_n\}{A1?,A2?,…,An?} 的冪集為 UUU,那么我們可以枚舉 UUU 中所有元素,寫出來容斥原理的公式:
S(?i=1nAi)=∑B∈P(?1)∣B∣?1S(?Ai∈BAi)S(\bigcup_{i = 1}^nA_i) = \sum_{B \in P}(-1)^{|B| - 1}S(\bigcap_{A_i \in B}A_i) S(i=1?n?Ai?)=B∈P∑?(?1)∣B∣?1S(Ai?∈B??Ai?)
(不得不說容斥原理的公式寫成這個樣子真的簡潔明了又暴力,直接枚舉了 2n2^n2n 種集合)
首先需要明確的是,我們使用容斥原理一定是要有一個出發點的,就是對于某一類集合,我們可以快速統計出來這一類集合的答案之和,因為我們不可能花費 O(2n)O(2^n)O(2n) 的時間復雜度去枚舉所有 AiA_iAi? 的交集情況,在集合數繁多的情況下我們只能對這些集合進行分類合并。
對于本題來說,這個分類方法可以很自然地得出。
我們思考若干集合的交,例如 A1∩A3∩A6A_1 \cap A_3 \cap A_6A1?∩A3?∩A6?,那么在這個集合中的元素一定是 a[1],a[3],a[6]a[1], a[3], a[6]a[1],a[3],a[6] 的公倍數,即一定是 lcm(a[1],a[3],a[6])lcm(a[1], a[3], a[6])lcm(a[1],a[3],a[6]) 的倍數,并且 000 到 mmm 內所有 a[1],a[3],a[6]a[1], a[3], a[6]a[1],a[3],a[6] 的公倍數一定在這個集合中。
對于任意一組集合的并皆是如此,并且,我們不難發現,由于 a[i]a[i]a[i] 都是 mmm 的因數,那么若干個 a[i]a[i]a[i] 的最小公倍數也一定是 mmm 的因數。
所以,我們不妨把集合按照最小公倍數分類來進行容斥。
首先,根據上面的結論,我們有:
S(?Ai∈BAi)=12lml(ml?1)=12m(ml?1)S(\bigcap_{A_i \in B} A_i) = \frac 12 l\frac ml(\frac ml - 1) = \frac 12m(\frac ml - 1) S(Ai?∈B??Ai?)=21?llm?(lm??1)=21?m(lm??1)
其中 lll 為所有 Ai∈BA_i \in BAi?∈B 的 iii 中 a[i]a[i]a[i] 的最小公倍數。
我們不妨設
l=LCM(B)=lcmAi∈Ba[i]l = LCM(B) = {lcm}_{A_i \in B} a[i] l=LCM(B)=lcmAi?∈B?a[i]
那么我們就可以以對集合按照最小公倍數分類的方式重寫容斥原理。
S(?i=1nAi)=∑l∣m∑B∈P[LCM(B)=l](?1)∣B∣?1S(?Ai∈BAi)S(\bigcup_{i = 1}^nA_i) = \sum_{l|m}\sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1}S(\bigcap_{A_i \in B}A_i) S(i=1?n?Ai?)=l∣m∑?B∈P∑?[LCM(B)=l](?1)∣B∣?1S(Ai?∈B??Ai?)
=∑l∣m∑B∈P[LCM(B)=l](?1)∣B∣?112m(ml?1)= \sum_{l|m}\sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1}\frac 12m(\frac ml - 1) =l∣m∑?B∈P∑?[LCM(B)=l](?1)∣B∣?121?m(lm??1)
=12m∑l∣m(ml?1)∑B∈P[LCM(B)=l](?1)∣B∣?1= \frac 12m\sum_{l|m}(\frac ml - 1)\sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1} =21?ml∣m∑?(lm??1)B∈P∑?[LCM(B)=l](?1)∣B∣?1
接下來,我們只需要考慮如何計算
∑B∈P[LCM(B)=l](?1)∣B∣?1\sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1} B∈P∑?[LCM(B)=l](?1)∣B∣?1
這一坨式子。
這里我們需要用到一個結論,也就是非常出名的莫比烏斯反演公式:
如果有函數 f(n),g(n)f(n), g(n)f(n),g(n) 滿足:
g(n)=∑d∣nf(d)g(n) = \sum_{d|n}f(d) g(n)=d∣n∑?f(d)
那么他們同時也滿足:
f(n)=∑d∣nμ(nd)g(d)f(n) = \sum_{d|n}\mu(\frac nd)g(d) f(n)=d∣n∑?μ(dn?)g(d)
這是一個非常非常非常有用的結論,他可以允許我們在枚舉最大公約數或最小公倍數時去掉最大/最小,改為枚舉公約數或者公倍數。這里的 μ\muμ 是莫比烏斯函數,關于莫比烏斯反演在我另一篇博客中有講解,可以移步去看,不過這里我們只需要知道這個結論就行了。
在這里,我們不妨設
f(l)=∑B∈P[LCM(B)=l](?1)∣B∣?1f(l) = \sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1} f(l)=B∈P∑?[LCM(B)=l](?1)∣B∣?1
那么我們不難發現對于
g(n)=∑d∣nf(d)g(n) = \sum_{d|n}f(d) g(n)=d∣n∑?f(d)
來說,f(n)f(n)f(n) 表示所有最小公倍數為 nnn 的集合 BBB 的 (?1)∣B∣?1(-1)^{|B| - 1}(?1)∣B∣?1 的和,那么 g(n)g(n)g(n) 即表示所有公倍數為 nnn 的集合 BBB 的 (?1)∣B∣?1(-1)^{|B| - 1}(?1)∣B∣?1 的和。
我們通過求出來 g(n)g(n)g(n) 的式子,然后利用莫比烏斯反演的公式來間接求出 f(n)f(n)f(n) 的式子。
g(n)g(n)g(n) 的式子非常好求,我們只需要知道數組 a[i]a[i]a[i] 中為 nnn 的約數的數的個數即可,假設個數為 xxx。
那么這些約數中任意若干個約數組成的集合都滿足公約數為 nnn,即
g(n)=∑i=1x(xi)(?1)i?1=1?(1?1)xg(n) = \sum_{i = 1}^x{x \choose i}(-1)^{i - 1} = 1 - (1 - 1)^x g(n)=i=1∑x?(ix?)(?1)i?1=1?(1?1)x
我們可以得到,當數組 a[i]a[i]a[i] 中為 nnn 的約數的個數為 000 時,g(n)=0g(n) = 0g(n)=0,否則 g(n)=1g(n) = 1g(n)=1。
我們把這個式子代入原式:
S(?i=1nAi)=12m∑l∣m(ml?1)f(l)S(\bigcup_{i = 1}^nA_i) = \frac 12m\sum_{l|m}(\frac ml - 1)f(l) S(i=1?n?Ai?)=21?ml∣m∑?(lm??1)f(l)
=12m∑l∣m(ml?1)∑d∣lμ(ld)g(d)= \frac 12m\sum_{l|m}(\frac ml - 1)\sum_{d|l}\mu(\frac ld)g(d) =21?ml∣m∑?(lm??1)d∣l∑?μ(dl?)g(d)
我們不妨交換一下求和順序,將 g(d)g(d)g(d) 提前,得到
S(?i=1nAi)=12m∑d∣mg(d)∑l∣mdμ(l)(mdl?1)S(\bigcup_{i = 1}^nA_i) = \frac 12m\sum_{d|m}g(d)\sum_{l|\frac md}\mu(l)(\frac m{dl} - 1) S(i=1?n?Ai?)=21?md∣m∑?g(d)l∣dm?∑?μ(l)(dlm??1)
我們設
T(n)=∑d∣nμ(d)(nd?1)=∑d∣nμ(d)nd?∑d∣nμ(d)=?(n)?e(n)T(n) = \sum_{d|n}\mu(d)(\frac nd - 1) = \sum_{d|n}\mu(d)\frac nd - \sum_{d|n}\mu(d) = \phi(n) - e(n) T(n)=d∣n∑?μ(d)(dn??1)=d∣n∑?μ(d)dn??d∣n∑?μ(d)=?(n)?e(n)
這里的 ?(n)\phi(n)?(n) 是歐拉函數,e(n)e(n)e(n) 是單位函數,僅當 n=1n = 1n=1 時 e(n)=1e(n) = 1e(n)=1,否則 e(n)=0e(n) = 0e(n)=0。
如果你不知道什么是歐拉函數或者單位函數,那你就把它當做一個普通積性函數就可以了,我們仍可以通過積性函數的性質用篩法篩出來函數的值。
所以,最終答案為:
S(?i=1nAi)=12m∑d∣mg(d)T(nd)S(\bigcup_{i = 1}^nA_i) = \frac 12m\sum_{d|m}g(d)T(\frac nd) S(i=1?n?Ai?)=21?md∣m∑?g(d)T(dn?)
=12m∑d∣mg(d)[?(nd)?e(nd)]= \frac 12m\sum_{d|m}g(d)[\phi(\frac nd) - e(\frac nd)] =21?md∣m∑?g(d)[?(dn?)?e(dn?)]
這樣,我們就可以先求出來 mmm 的所有約數,然后對于每個約數 ddd,求出來 g(d),?(d)g(d), \phi(d)g(d),?(d) 的值。
時間復雜度為 O(d(m)n)O(d(m)n)O(d(m)n),其中 d(m)d(m)d(m) 為 mmm 的因數個數,這個值很小,最大只有不到 400040004000 個(據說)。
然而最終代碼還是跑得很快的,甚至只需要 71ms71ms71ms。
#include <bits/stdc++.h>const int MAXN = 1e5 + 5;int a[MAXN], ddiv[MAXN], g[MAXN], phi[MAXN], n, m, cnt, prime[MAXN], cnt2;int find(int x) {return std::lower_bound(ddiv + 1, ddiv + cnt + 1, x) - ddiv; }int e(int x) {return x == 1; }void solve(int T) {scanf("%d%d", &n, &m);cnt = cnt2 = 0;/*memset(g, 0, sizeof(g));memset(phi, 0, sizeof(phi));memset(ddiv, 0, sizeof(ddiv));memset(prime, 0, sizeof(prime));*/for(int i = 1; i <= n; i++) {int x;scanf("%d", &x);a[i] = std::__gcd(x, m);}std::sort(a + 1, a + n + 1);n = std::unique(a + 1, a + n + 1) - a - 1;for(int i = 1; i * i <= m; i++) {if(m % i != 0) continue;int d1 = i, d2 = m / i;ddiv[++cnt] = d1;if(d1 != d2) ddiv[++cnt] = d2;}std::sort(ddiv + 1, ddiv + cnt + 1);phi[1] = 1;for(int i = 2; i <= cnt; i++) {phi[i] = ddiv[i] - 1;for(int j = 1; j <= cnt2; j++) {if(ddiv[i] % prime[j] != 0) continue;int t1 = ddiv[i] / prime[j];if(t1 % prime[j] == 0) phi[i] = phi[find(t1)] * prime[j];else phi[i] = phi[find(t1)] * (prime[j] - 1);}if(phi[i] == ddiv[i] - 1) prime[++cnt2] = ddiv[i];}for(int i = 1; i <= cnt; i++) {g[i] = 0;for(int j = 1; j <= n; j++)if(ddiv[i] % a[j] == 0) {g[i] = 1; break;}}long long ans = 0;for(int i = 1; i <= cnt; i++) ans = ans + 1LL * g[i] * (phi[find(m / ddiv[i])] - (i == cnt));ans = ans * m / 2;printf("Case #%d: %lld\n", T, ans); }int main() {int T;scanf("%d", &T);for(int i = 1; i <= T; i++) solve(i);return 0; }總結
以上是生活随笔為你收集整理的Frogs - HDU5514的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在线批量无损压缩图片工具
- 下一篇: 零基础数据分析的我用了半年时间利用信用卡