zoukankan      html  css  js  c++  java
  • 【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;
        
    }
  • 相关阅读:
    Redis持久化——AOF日志
    设计原则:接口隔离原则(ISP)
    设计原则:里式替换原则(LSP)
    新入职一家公司如何快速进入工作状态
    又是一年毕业季——如何入坑程序员
    设计原则:开闭原则(OCP)
    设计原则:单一职责(SRP)原则
    Redis持久化——内存快照(RDB)
    工作中应该如何管理自己的情绪?
    如何成为一个精力充沛的程序员——掌控
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196391.html
Copyright © 2011-2022 走看看