• 【BZOJ 2818】 GCD


    【题目链接】

              点击打开链接

    【算法】

              线性筛出不大于N的所有素数,枚举gcd(x,y)(设为p),问题转化为求(x,y)=p的个数
              设x=x'p, y=y'p,那么有(x,y)=1且1≤x,y≤N/p

              转化为求(x,y)=1且1≤x,y≤n的个数

              求(x,y)=1且1≤x,y≤N的个数:

              若x≥y,对于x=1..n,有ϕ(x)个y满足(x,y)=1
              若x≤y,对于y=1..n,有ϕ(y)个x满足(x,y)=1
              若x=y,只有一种情况:(x=1, y=1)
              所以答案为2(ϕ(1)+...+ϕ(n))-1

              线性筛筛出欧拉函数、预处理前缀和即可

    【代码】

               

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll MAXN = 1e7;
    
    ll i,N,tot,ans;
    ll sum[MAXN+10];
    int prime[MAXN+10],phi[MAXN+10];
    
    template <typename T> inline void read(T &x) {
            ll f = 1; x = 0;
            char c = getchar();
            for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
            for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
            x *= f;
    }
    
    template <typename T> inline void write(T x) {
        if (x < 0) { putchar('-'); x = -x; }
        if (x > 9) write(x/10);
        putchar(x%10+'0');
    }
    
    template <typename T> inline void writeln(T x) {
        write(x);
        puts("");
    }
    
    inline void sieve(ll n) {
            ll i,j,tmp;
            static ll f[MAXN+10];
            phi[1] = 1;
            for (i = 2; i <= n; i++) {
                    if (!f[i]) {
                            prime[++tot] = f[i] = i;
                            phi[i] = i - 1;
                    }
                    for (j = 1; j <= tot; j++) {
                            tmp = i * prime[j];
                            if (tmp > n) break;
                            f[tmp] = prime[j];
                            phi[tmp] = (prime[j] - (prime[j] < f[i])) * phi[i];
                            if (f[i] == prime[j]) break;
                    }
            }    
    }
    
    int main() {
            
            read(N);
            sieve(N);
            for (i = 1; i <= N; i++) sum[i] = sum[i-1] + phi[i];
            for (i = 1; i <= tot; i++) ans = ans + 2 * sum[N/prime[i]] - 1;
            writeln(ans);
            
            return 0;
        
    }
  • 相关阅读:
    grab jpegs from v4l2 devices
    c helloworld on zynq
    minicom installation and configuration on ubuntu
    DBA的做法
    sqlserver锁表、解锁、查看销表
    linux内核分析(网课期末&地面课期中)
    Linux内核分析实验八------理解进程调度时机跟踪分析进程调度与
    LINUX内核分析第七周——可执行程序的装载
    Linux内核分析实验六
    Linux内核分析实验五
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196391.html
Copyright © 2020-2023  润新知