zoukankan      html  css  js  c++  java
  • CF 585 E Present for Vitalik the Philatelist

    CF 585 E Present for Vitalik the Philatelist

    我们假设 $ f(x) $ 表示与 $ x $ 互质的数的个数,$ s(x) $ 为 gcd 为 $ x $ 的集合的个数。

    那么显然答案就是

    [sum_{i > 1} f(i)s(i) ]

    所以我们现在考虑怎么求 $ f $ 和 $ s $ 。

    先考虑 $ f $ ,

    [f(x) = sum_{i} [gcd(i,x) = 1] c_i\f(x) = sum_{i} c_i sum_{d|gcd(i,x)} mu(d)\f(x) = sum_{d | x} mu(d) sum_{d|i} c_i ]

    我们设 $ t(x) = sum_{x|i} c_i $ ,不难发现这就是我的 这篇博客 里面的第二种卷积,可以筛出来。

    那么

    [f(x) = sum_{d|x} mu(d) t(d) ]

    然后又可以用第一种卷积来做,于是我们就跑出了 $ f $ 。

    现在考虑怎么求 $ s $ ,我们可以假设 $ s'(x) $ 就是 gcd 为 $ x $ 的倍数的所有集合的个数。我们需要算出 $ x $ 的倍数的数字个数,就是 $ sum_{x|i} c_i $ ,这个不就是前面的 $ t(x) $ 吗!

    所以显然有

    [s'(x) = 2^{t(x)} - 1 ]

    同时我们知道

    [s'(x) = sum_{x|d} s(d) ]

    这个东西就是第二个卷积的反过来的形式,也就是第四种卷积!

    所以我们可以三次 $ O(wloglog w) $ 跑过去啦。

    开始看错 $ w $ 大小了。。MLE了两发。。

    #include "iostream"
    #include "algorithm"
    #include "cstring"
    #include "cstdio"
    #include "queue"
    using namespace std;
    #define MAXN 10000006
    #define P 1000000007
    int n;
    int A[500006] , c[MAXN] , _[500006] , mu[MAXN] , s[MAXN];
    int pri[MAXN] , en , lim;
    void sieve( int x ) {
        pri[0] = 1; mu[1] = 1;
        for( int i = 2 ; i <= x ; ++ i ) {
            if( !pri[i] ) pri[++ en] = i , mu[i] = -1;
            for( int j = 1 ; i * pri[j] <= x && j <= en ; ++ j ) {
                pri[i * pri[j]] = 1;
                if( i % pri[j] == 0 ) { mu[i * pri[j]] = 0; break; }
                mu[i * pri[j]] = -mu[i];
            }
        }
    }
    signed main() {
    //    freopen("in","r",stdin);
        cin >> n;
        for( int i = 1 ; i <= n ; ++ i ) scanf("%d",&A[i]) , ++ c[A[i]] , lim = max( lim , A[i] );
        sieve( lim );
        for( int i = 1 ; i <= en ; ++ i )
            for( int j = lim / pri[i] ; j ; -- j )
                c[j] += c[j * pri[i]];
        for( int i = 1 ; i <= lim ; ++ i ) mu[i] *= c[i];
        for( int i = 1 ; i <= en ; ++ i )
            for( int j = 1 ; j * pri[i] <= lim ; ++ j )
                ( mu[j * pri[i]] += mu[j] ) %= P;
        _[0] = 1;for( int i = 1 ; i < 500006 ; ++ i ) _[i] = _[i - 1] * 2 % P;
        for( int i = 1 ; i <= lim ; ++ i ) s[i] = _[c[i]] - 1;
        for( int i = en ; i ; -- i )
            for( int j = 1 ; j * pri[i] <= lim ; ++ j )
                ( s[j] -= s[j * pri[i]] ) %= P;
        int ans = 0;
        for( int i = 2 ; i <= lim ; ++ i ) ( ans += 1ll * s[i] * mu[i] % P ) %= P;
        cout << ( ans + P ) % P << endl;
    }
    
  • 相关阅读:
    Android——继续深造——从安装Android Studio 2.0开始(详)
    PHP——安装wampserver丢失MSVCR110.dll
    Marza Gift for GDC 2016
    Retrieve OpenGL Context from Qt 5.5 on OSX
    Space Time Varying Color Palette
    Screen Space Depth Varying Glow based on Heat Diffusion
    Visualization of Detail Point Set by Local Algebraic Sphere Fitting
    Glass Dragon
    Jump Flood Algorithms for Centroidal Voronoi Tessellation
    京都之行
  • 原文地址:https://www.cnblogs.com/yijan/p/12356913.html
Copyright © 2011-2022 走看看