• AcWing


    https://www.acwing.com/problem/content/222/

    求n以内gcd为质数的数对个数。

    其实要是n和m不一样的话,貌似是要下面这样做的。也就是n和m不一样可能都得反演,下面这个是nlogn左右的,瓶颈在于给每个T刷上他的质因子p对应的mu[T/p]。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 1e7;
    int Sum[MAXN + 5];
    
    char mu[MAXN + 5];
    int p[(MAXN) / 10 + 5], ptop;
    bitset < MAXN + 5 > np;
    
    void sieve(int n = MAXN) {
        np[1] = mu[1] = 1;
        for(int i = 2; i <= n; i++) {
            if(!np[i])
                p[++ptop] = i, mu[i] =  - 1;
            for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
                np[t] = 1;
                if(i % p[j])
                    mu[t] = -mu[i];
                else {
                    mu[t] = 0;
                    break;
                }
            }
        }
        for(int i = 1; i <= ptop; ++i) {
            for(int cnt = 1, x = p[i]; x <= n; x += p[i], ++cnt) {
                Sum[x] += mu[cnt];
            }
        }
        for(int i = 1; i <= n; ++i) {
            Sum[i] += Sum[i - 1];
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n;
        scanf("%d", &n);
        sieve(n);
        ll sum = 0;
        for(int l = 1, r; l <= n; l = r + 1) {
            r = n / (n / l);
            sum += 1ll * (n / l) * (n / l) * (Sum[r] - Sum[l - 1]);
        }
        printf("%lld
    ", sum);
    }
    

    上网找了一个奇怪的线性筛,开眼界,什么都可以筛,根据最小质因子的个数进行分类讨论,这种解法是可以解决n和m不一样的问题的。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 1e7;
    int Sum[MAXN + 5];
    
    char mu[MAXN + 5];
    int p[(MAXN) / 10 + 5], ptop;
    bitset < MAXN + 5 > np;
    
    void sieve(int n = MAXN) {
        //Sum[T]表示T的所有质数因子p的mu[T/p]之和
        np[1] = mu[1] = 1;
        Sum[1] = 0;
        for(int i = 2; i <= n; i++) {
            if(!np[i]) {
                p[++ptop] = i, mu[i] =  - 1;
                Sum[i] = mu[1];
            }
            for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
                np[t] = 1;
                if(i % p[j]) {
                    mu[t] = -mu[i];
                    Sum[t] = -Sum[i] + mu[i];
                } else {
                    mu[t] = 0;
                    //T有>=2个p
                    //当T有2个p时,只有除掉p可能会有结果,此时为Sum[T]=mu[y]
                    //当T有>=3个p时,结果都是0,此时也是Sum[T]=mu[y]
                    Sum[t] = mu[i];
                    break;
                }
            }
        }
    
        for(int i = 1; i <= n; ++i) {
            Sum[i] += Sum[i - 1];
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n;
        scanf("%d", &n);
        sieve(n);
        ll sum = 0;
        for(int l = 1, r; l <= n; l = r + 1) {
            r = n / (n / l);
            sum += 1ll * (n / l) * (n / l) * (Sum[r] - Sum[l - 1]);
        }
        printf("%lld
    ", sum);
    }
    

    但是貌似因为n和m一样就可以简化。直接使用欧拉函数就完事了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 1e7;
    
    ll phi[MAXN + 5];
    int p[MAXN / 10 + 5], ptop;
    
    void sieve(int n) {
        phi[1] = 1;
        for(int i = 2; i <= n; i++) {
            if(!phi[i])
                p[++ptop] = i, phi[i] = i - 1;
            for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
                if(i % p[j])
                    phi[t] = phi[i] * (p[j] - 1);
                else {
                    phi[t] = phi[i] * p[j];
                    break;
                }
            }
        }
        for(int i = 1; i <= n; ++i) {
            phi[i] += phi[i - 1];
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n;
        scanf("%d", &n);
        sieve(n);
        ll res = 0;
        for(int i = 1; i <= ptop; ++i) {
            res += 2ll * phi[n / p[i]] - 1ll;
        }
        printf("%lld
    ", res);
    }
    

    需要注意的是bitset比bool慢多了,bitset只是对比整数可能会有优势,或者拿来省空间,但实际上在线性筛里面都可以对待筛函数赋值一个奇怪的东西使这个数组变的不必要。

  • 相关阅读:
    radio按钮组和label标签
    div布局
    bootstrap模态框使用
    bootstrap按钮组下拉菜单使用
    Bootstrap下拉菜单和导航栏的使用
    Bootstrap源码解读下拉菜单
    python中django学习2
    windows下配置桌面github
    状态模式--无尽加班何时休
    直接在安装了redis的Linux机器上操作redis数据存储类型--set类型
  • 原文地址:https://www.cnblogs.com/Inko/p/11449603.html
Copyright © 2020-2023  润新知