Codeforces 585E 莫比乌斯反演 + 容斥

       给定 n ( 2 ≤ n ≤ 5 e 5 ) n(2\le n\le 5e5) n(2n5e5) 个数, 2 ≤ a i ≤ 1 e 7 2\le a_i\le 1e7 2ai1e7

       一次操作中,从数组 a a a 中选定一个 x x x,再从剩下的数中选出一个 gcd ⁡ > 1 \gcd>1 gcd>1 的非空集合 Y Y Y,使得所有选中的数的 gcd ⁡ = 1 \gcd=1 gcd=1,即 gcd ⁡ ( x , Y ) = 1 \gcd(x,Y)=1 gcd(x,Y)=1

       问有多少种这样的方案,答案 m o d   1 e 9 + 7 mod\ 1e9+7 mod 1e9+7

       我们尝试用公式表达出我们的所求:
∑ Y ⊆ U ∑ x ⊈ Y [ gcd ⁡ ( Y ) ≠ 1 ] [ gcd ⁡ ( x , Y ) = 1 ] \sum_{Y \subseteq U}\sum_{x\not\subseteq Y}[\gcd(Y)\neq1][\gcd(x,Y)=1] YUxY[gcd(Y)=1][gcd(x,Y)=1]

       当 gcd ⁡ ( Y ) = 1 \gcd(Y)=1 gcd(Y)=1 时, gcd ⁡ ( x , Y ) = 1 \gcd(x,Y)=1 gcd(x,Y)=1 必定满足,所以我们考虑用 gcd ⁡ ( x , Y ) = 1 \gcd(x,Y)=1 gcd(x,Y)=1 的所有情况减去 gcd ⁡ ( Y ) = 1 \gcd(Y)=1 gcd(Y)=1 的所有情况。

       即上式变为 :
∑ Y ⊆ U ∑ x ⊈ Y [ gcd ⁡ ( x , Y ) = 1 ] − ∑ Y ⊆ U ∑ x ⊈ Y [ gcd ⁡ ( Y ) = 1 ] \sum_{Y \subseteq U}\sum_{x\not\subseteq Y}[\gcd(x,Y)=1]-\sum_{Y \subseteq U}\sum_{x\not\subseteq Y}[\gcd(Y)=1] YUxY[gcd(x,Y)=1]YUxY[gcd(Y)=1]

       先考虑前半部分,当我们从一个 gcd ⁡ = 1 \gcd=1 gcd=1 的集合 Z ( ∣ Z ∣ > 1 ) Z(|Z|>1) Z(Z>1) 取出任何一个元素 x x x,都满足 gcd ⁡ ( x , Z − x ) = 1 \gcd(x,Z-x)=1 gcd(x,Zx)=1,也就是说 Z − x Z-x Zx 就是我们要找的集合 Y Y Y

       所以所有的集合产生的贡献就可以表述成:
∑ Y ⊆ U ∑ x ⊈ Y [ gcd ⁡ ( x , Y ) = 1 ] = ∑ ∣ Z ∣ > 1 , Z ⊆ U [ gcd ⁡ ( Z ) = 1 ] ∣ Z ∣ \sum_{Y \subseteq U}\sum_{x\not\subseteq Y}[\gcd(x,Y)=1]=\sum_{|Z|>1,Z\subseteq U}[\gcd(Z)=1]|Z| YUxY[gcd(x,Y)=1]=Z>1,ZU[gcd(Z)=1]Z

       对于一个集合 Z Z Z,贡献总共 ∣ Z ∣ |Z| Z 种构造 x x x Y Y Y 的方法。

       我们令 m m m a i a_i ai 中为 d d d 的倍数的数的数量。

∑ ∣ Z ∣ > 1 , Z ⊆ U [ gcd ⁡ ( Z ) = 1 ] ∣ Z ∣ = ∑ ∣ Z ∣ > 1 , Z ⊆ U ∑ d ∣ gcd ⁡ ( Z ) μ ( d ) ∣ Z ∣ = ∑ d = 1 m a x ( a i ) μ ( d ) ∑ ∣ Z ∣ = 2 m C m ∣ Z ∣ ∗ ∣ Z ∣ \begin{aligned}\sum_{|Z|>1,Z\subseteq U}[\gcd(Z)=1]|Z|&=\sum_{|Z|>1,Z\subseteq U}\sum_{d|\gcd(Z)}\mu(d)|Z| \\&=\sum_{d=1}^{max(a_i)}\mu(d)\sum_{|Z|=2}^{m}C_{m}^{|Z|}*|Z| \end{aligned} Z>1,ZU[gcd(Z)=1]Z=Z>1,ZUdgcd(Z)μ(d)Z=d=1max(ai)μ(d)Z=2mCmZZ

        ∑ ∣ Z ∣ = 2 m C m ∣ Z ∣ ∗ ∣ Z ∣ \sum_{|Z|=2}^{m}C_{m}^{|Z|}*|Z| Z=2mCmZZ 可以表述成 ∑ i = 2 n C n i ∗ i \sum_{i=2}^{n}C_{n}^i*i i=2nCnii,我们令 f ( n ) = ∑ i = 1 n C n i ∗ i f(n)=\sum_{i=1}^{n}C_{n}^i*i f(n)=i=1nCnii

       则上述式子写成:
∑ d = 1 m a x ( a i ) μ ( d ) ( f ( m ) − m ) \sum_{d=1}^{max(a_i)}\mu(d)(f(m)-m) d=1max(ai)μ(d)(f(m)m)

       根据组合数学公式 ( 1 + x ) n = ∑ i = 0 n C n i ∗ x i (1+x)^n=\sum_{i=0}^nC_n^i*x^i (1+x)n=i=0nCnixi,两边求导可得 ∑ i = 0 n C n i ∗ i = n ∗ 2 n − 1 \sum_{i=0}^{n}C_{n}^i*i=n*2^{n-1} i=0nCnii=n2n1 (而 i = 0 i=0 i=0 时无贡献可省去,即为上式)。

       则有 f ( x ) = 2 f ( x − 1 ) + 2 x − 1 f(x)=2f(x-1)+2^{x-1} f(x)=2f(x1)+2x1

       再考虑后半部分,道理类似,任意集合 Y Y Y,产生的贡献为 n − ∣ Y ∣ n-|Y| nY n − ∣ Y ∣ n-|Y| nY 即为 x x x 的数量:

∑ Y ⊆ U ∑ x ⊈ Y [ gcd ⁡ ( Y ) = 1 ] = ∑ Y ⊆ U [ gcd ⁡ ( Y ) = 1 ] ( n − ∣ Y ∣ ) = ∑ Y ⊆ U ∑ d ∣ gcd ⁡ ( Y ) μ ( d ) ∗ ( n − ∣ Y ∣ ) = ∑ d = 1 m a x ( a i ) μ ( d ) ( ( n ∗ ∑ ∣ Y ∣ = 1 m C m i ) − ( ∑ ∣ Y ∣ = 1 m C m i ∗ ∣ Y ∣ ) ) = ∑ d = 1 m a x ( a i ) μ ( d ) ( n ∗ ( 2 m − 1 ) − f ( m ) ) \begin{aligned}\sum_{Y \subseteq U}\sum_{x\not\subseteq Y}[\gcd(Y)=1]&=\sum_{Y \subseteq U}[\gcd(Y)=1](n-|Y|)\\&=\sum_{Y \subseteq U}\sum_{d | \gcd(Y)}\mu(d)*(n-|Y|)\\&=\sum_{d=1}^{max(a_i)}\mu(d)((n*\sum_{|Y|=1}^mC_m^i)-(\sum_{|Y|=1}^mC_m^i*|Y|))\\&=\sum_{d=1}^{max(a_i)}\mu(d)(n*(2^m-1)-f(m))\end{aligned} YUxY[gcd(Y)=1]=YU[gcd(Y)=1](nY)=YUdgcd(Y)μ(d)(nY)=d=1max(ai)μ(d)((nY=1mCmi)(Y=1mCmiY))=d=1max(ai)μ(d)(n(2m1)f(m))

       合并起来可得:

∑ d = 1 m a x ( a i ) μ ( d ) ( f ( m ) − m ) − ∑ d = 1 m a x ( a i ) μ ( d ) ( n ∗ ( 2 m − 1 ) − f ( m ) ) = ∑ d = 1 m a x ( a i ) μ ( d ) ( 2 f ( m ) − m − n ∗ ( 2 m − 1 ) ) \sum_{d=1}^{max(a_i)}\mu(d)(f(m)-m)-\sum_{d=1}^{max(a_i)}\mu(d)(n*(2^m-1)-f(m))=\sum_{d=1}^{max(a_i)}\mu(d)(2f(m)-m-n*(2^m-1)) d=1max(ai)μ(d)(f(m)m)d=1max(ai)μ(d)(n(2m1)f(m))=d=1max(ai)μ(d)(2f(m)mn(2m1))

       其中 f ( 1 ) = 1 , f ( x ) = 2 f ( x − 1 ) + 2 x − 1 f(1)=1,f(x)=2f(x-1)+2^{x-1} f(1)=1,f(x)=2f(x1)+2x1

       这里有一个小 t r i c k trick trick,我们不需要枚举 a i a_i ai 的因子来计算贡献。而是通过统计每个 a i a_i ai 的贡献,然后利用枚举 d d d 的同时,统计它的倍数的贡献(调和级数复杂度 n l o g n nlogn nlogn,如果枚举 a i a_i ai 的因子则是 n a i n\sqrt{a_i} nai 复杂度)

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define endl '\n'
typedef long long LL;
const int maxn = 1e7 + 1;
const LL mod = 1e9 + 7;

int bit[maxn], f[maxn], d[maxn], mu[maxn], prime[maxn], cnt;
bool judge[maxn];

inline void init(){
    mu[1] = 1;
    for(int i = 2; i < maxn; i++){
        if(!judge[i]){
            prime[++cnt] = i;
            mu[i] = -1;
        }
        for(int j = 1, v; j <= cnt && (v = i * prime[j]) < maxn; j++){
            judge[v] = true;
            if(!(i % prime[j])) break;
            mu[v] = -mu[i];
        }
    }
    f[1] = 1;
    bit[0] = 1;
    bit[1] = 2;
    for(int i = 2; i < maxn; i++){
        f[i] = (2LL * f[i - 1] + bit[i - 1]) % mod;
        bit[i] = bit[i - 1] * 2LL % mod;
    }
}

int main(){
    IOS;
    init();
    int n, a;
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a;
        d[a]++;
    }
    int ans = mu[1] * (2LL * f[n] % mod - n - n * (bit[n] - 1LL) % mod) % mod;
    for(int i = 2; i < maxn; i++){
        if(mu[i]){
            int tol = 0;
            for(int j = i; j < maxn; j += i) tol += d[j];
            ans = (ans + mu[i] * (2LL * f[tol] % mod - tol - n * (bit[tol] - 1LL) % mod)) % mod;
        }
    }
    cout << (ans + mod) % mod << endl;
}
### Codeforces 887E Problem Solution and Discussion The problem **887E - The Great Game** on Codeforces involves a strategic game between two players who take turns to perform operations under specific rules. To tackle this challenge effectively, understanding both dynamic programming (DP) techniques and bitwise manipulation is crucial. #### Dynamic Programming Approach One effective method to approach this problem utilizes DP with memoization. By defining `dp[i][j]` as the optimal result when starting from state `(i,j)` where `i` represents current position and `j` indicates some status flag related to previous moves: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = ...; // Define based on constraints int dp[MAXN][2]; // Function to calculate minimum steps using top-down DP int minSteps(int pos, bool prevMoveType) { if (pos >= N) return 0; if (dp[pos][prevMoveType] != -1) return dp[pos][prevMoveType]; int res = INT_MAX; // Try all possible next positions and update 'res' for (...) { /* Logic here */ } dp[pos][prevMoveType] = res; return res; } ``` This code snippet outlines how one might structure a solution involving recursive calls combined with caching results through an array named `dp`. #### Bitwise Operations Insight Another critical aspect lies within efficiently handling large integers via bitwise operators instead of arithmetic ones whenever applicable. This optimization can significantly reduce computation time especially given tight limits often found in competitive coding challenges like those hosted by platforms such as Codeforces[^1]. For detailed discussions about similar problems or more insights into solving strategies specifically tailored towards contest preparation, visiting forums dedicated to algorithmic contests would be beneficial. Websites associated directly with Codeforces offer rich resources including editorials written after each round which provide comprehensive explanations alongside alternative approaches taken by successful contestants during live events. --related questions-- 1. What are common pitfalls encountered while implementing dynamic programming solutions? 2. How does bit manipulation improve performance in algorithms dealing with integer values? 3. Can you recommend any online communities focused on discussing competitive programming tactics? 4. Are there particular patterns that frequently appear across different levels of difficulty within Codeforces contests?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值