zoukankan      html  css  js  c++  java
  • bzoj 4804. 欧拉心算 莫比乌斯反演

    bzoj4804. 欧拉心算

    题目链接

    ​ 莫比乌斯反演。

    ​ 要化简这个式子:(displaystyle sum_{i = 1}^{n} sum_{j = 1}^{n} phi(gcd(i, j)))

    ​ 可以化简为:(displaystyle sum_{T = 1}^{min(n, m)} lfloor frac{n}{T} floor ^ 2 sum_{d mid T}^{min(n, m)} phi(d) mu(T / d))

    ​ 这道题得用线性筛,设(f(T) = displaystyle sum_{d mid T}^{min(n, m)} phi(d) mu(T / d)), 可以用线性筛筛出(f)甩链接

    ​ 必须用整除分块,不然过不了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
        long long s = 0, f = 1; char ch;
        while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
        for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
        return s * f;
    }
    
    const int N = 1e7 + 5;
    
    int t, n, cnt;
    int mu[N], phi[N], prime[N];
    bool is_prime[N];
    long long f[N];
    
    void make_phi_mu() {
        mu[1] = phi[1] = f[1] = 1;
        for(int i = 2;i <= N - 5; i++) {
            if(!is_prime[i]) prime[++cnt] = i, mu[i] = -1, phi[i] = i - 1, f[i] = i - 2;
            for(int j = 1;j <= cnt && i * prime[j] <= N - 5; j++) {
                is_prime[i * prime[j]] = 1;
                if(!(i % prime[j])) {
                    phi[i * prime[j]] = phi[i] * prime[j];
                    mu[i * prime[j]] = 0;
                    if((i / prime[j]) % prime[j]) f[i * prime[j]] = f[i / prime[j]] * 1ll * (prime[j] - 1) * (prime[j] - 1);
                    else f[i * prime[j]] = f[i] * prime[j];
                    break;
                }
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
                mu[i * prime[j]] = -mu[i];
                f[i * prime[j]] = f[i] * (prime[j] - 2);
            }
        }
        for(int i = 2;i <= N - 5; i++) f[i] += f[i - 1];
    }
    
    int main() {
    
        make_phi_mu();
    
        t = read();
        while(t --> 0) {
            n = read(); long long ans = 0; int last;
            for(int T = 1;T <= n; T = last + 1) {
                last = n / (n / T); 
                // cout << last << endl;
                ans += 1ll * (n / T) * (n / T) * (f[last] - f[T - 1]);
            }
            printf("%lld
    ", ans);
        }
    
    
        return 0;
    }
    
  • 相关阅读:
    oracle
    mysql的必知技巧
    sql_update
    sql查询
    Java 动态页面技术 之 jsp
    Java 会话技术 之 session
    Java 会话技术 之cookie
    Java HttpServletRequest
    Java HttpServletResponse
    Java Servlet接口、web.xml配置、HttpServlet父类
  • 原文地址:https://www.cnblogs.com/czhui666/p/13669619.html
Copyright © 2011-2022 走看看