• 洛谷


    https://www.luogu.org/problemnew/show/P2568

    统计n以内gcd为质数的数的个数。

    (sumlimits_p sumlimits_{i=1}^{n}sumlimits_{j=1}^{n} [gcd(i,j)==p])

    一开始还以为要莫比乌斯反演.

    推了半天不知道怎么求,遂看题解:

    $sumlimits_p sumlimits_{i=1}^{n}sumlimits_{j=1}^{n} [gcd(i,j)p] =sumlimits_p sumlimits_{i=1}^{frac{n}{p}}sumlimits_{j=1}^{frac{n}{p}} [gcd(i,j)1] $

    一个有序数对 ((i,j),(i>j))(i) 互质的数 (j) 的个数也就是 (varphi(i)) ,画一个正方形可以知道对调 ((i,j)) 求出一样的结果.

    但是当 $ i1&&j1 $ 时被重复计数了,要减去

    那么答案就是 $sumlimits_p (2*sumlimits_{i=1}^{frac{n}{p}}varphi(i) - 1) $

    
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    #define N 10000005
    
    int phi[N],pri[N],cntpri=0;
    bool notpri[N];
    
    ll prefix[N];
    
    void sieve_phi(int n) {
        notpri[1]=phi[1]=1;
        prefix[0]=0;
        prefix[1]=1;
        for(int i=2; i<=n; i++) {
            if(!notpri[i])
                pri[++cntpri]=i,phi[i]=i-1;
            for(int j=1; j<=cntpri&&i*pri[j]<=n; j++) {
                notpri[i*pri[j]]=1;
                if(i%pri[j])
                    phi[i*pri[j]]=phi[i]*phi[pri[j]];
                else {
                    phi[i*pri[j]]=phi[i]*pri[j];
                    break;
                }
            }
            prefix[i]=prefix[i-1]+phi[i];
        }
    }
    
    ll solve(ll n){
        ll ans=0;
        for(int i=1;i<=cntpri;i++){
            if(pri[i]<=n){
                ans+=2ll*(prefix[n/pri[i]])-1ll;
            }
        }
        return ans;
    }
    
    int main() {
        sieve_phi(10000000+1);
        int n;
        while(cin>>n) {
            ll ans=solve(n);
            cout<<ans<<endl;
        }
    }
    
    
  • 相关阅读:
    包介绍、日志模块及深浅拷贝
    一些常用模块
    RE模块(正则)
    软件开发规范
    模块及模块导入
    一些常用的内置函数总结
    迭代器、可迭代对象、迭代器对象
    多层装饰器例子
    闭包函数和装饰器
    递归、二分法、三元表达式及内置函数和匿名函数
  • 原文地址:https://www.cnblogs.com/Yinku/p/10666905.html
Copyright © 2020-2023  润新知