Codeforces 839D Winter is here - 暴力 - 容斥原理
Winter is here at the North and the White Walkers are close. John Snow has an army consisting of n soldiers. While the rest of the world is fighting for the Iron Throne, he is going to get ready for the attack of the White Walkers.
He has created a method to know how strong his army is. Let the i
Your task is to find the strength of his army. As the number may be very large, you have to print it modulo 1000000007 (109 + 7).
Greatest common divisor (gcd) of a sequence of integers is the maximum possible integer so that each element of the sequence is divisible by it.
The first line contains integer n (1 ≤ n ≤ 200000) — the size of the army.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 1000000) — denoting the strengths of his soldiers.
OutputPrint one integer — the strength of John Snow‘s army modulo 1000000007 (109 + 7).
Examples input3output
3 3 1
12input
4output
2 3 4 6
39Note
In the first sample the clans are {1}, {2}, {1, 2} so the answer will be 1·3 + 1·3 + 2·3 = 12
題目大意 給定n,集合A,設表示把這個集合內的所有數求最大公約數的結果,求。
根據常用套路,套一個循環去枚舉gcd的結果,然後再求系數,於是有
現在設,於是有
現在考慮求f(i)。可以想到容斥原理。
先假設所有的集合的gcd是i的倍數都符合條件然後計算答案(給定數集A中所有是i的倍數的數組成的集合任選一個子集),然後再減去f(2i), f(3i),...
現在要面臨兩個問題
- 第一次求值如何處理?
首先把式子寫出來,設這個集合的大小為n,那麽有因為
對兩邊同時進行求導得到
再帶入x = 1得到
- 設為是i的倍數的數的個數,如何快速求出?
根據定義式有
顯然超時。雖然這是暴力,但是不夠優美。
設表示,集合A中恰好為i的數有多少個。然後就可以得到總時間復雜度為O(mlog2m)的暴力:
最後求求和就完事了。
Code
1 /** 2 * Codeforces 3 * Problem#839D 4 * Accepted 5 * Time: 171ms 6 * Memory: 15400k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 11 const int lim = 1e6 + 1; 12 const int moder = 1e9 + 7; 13 14 int n; 15 int *a; 16 int *pow2; 17 int cnt[lim], counter[lim]; 18 int f[lim]; 19 int res = 0; 20 21 inline void init() { 22 scanf("%d", &n); 23 a = new int[(n + 1)]; 24 pow2 = new int[(n + 1)]; 25 pow2[0] = 1; 26 for(int i = 1; i <= n; i++) { 27 scanf("%d", a + i); 28 counter[a[i]]++; 29 pow2[i] = (pow2[i - 1] << 1) % moder; 30 } 31 } 32 33 inline void solve() { 34 for(int i = 1; i < lim; i++) 35 for(int j = i; j < lim; j += i) 36 cnt[i] += counter[j]; 37 38 for(int i = lim - 1; i > 1; i--) { 39 if(!cnt[i]) continue; 40 f[i] = (cnt[i] * 1LL * pow2[cnt[i] - 1]) % moder; 41 for(int j = i << 1; j < lim; j += i) 42 f[i] = (f[i] - f[j]) % moder; 43 if(f[i] < 0) f[i] += moder; 44 res = (res + (f[i] * 1LL * i) % moder) % moder; 45 } 46 47 printf("%d\n", res); 48 } 49 50 int main() { 51 init(); 52 solve(); 53 return 0; 54 }
Codeforces 839D Winter is here - 暴力 - 容斥原理