zoukankan      html  css  js  c++  java
  • 洛谷 P2568 GCD(欧拉定理 | | 莫比乌斯反演)

    题目描述

    给定整数N,求1<=x,y<=N(N<=1e7)且Gcd(x,y)为素数的数对(x,y)有多少对.

    输入输出样例

    输入样例#1:
    4
    输出样例#1:
    4

    题解

    此题有两种解法。
    1.欧拉函数
    很明显,可以枚举素数p,计算n/p的phi,然后统计出来乘以2,最后再特判x==y且x,y为素数的情况。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    int n,cnt;
    ll phi[10000001];
    int vis[10000001];
    int prime[10000001];
    ll sum=0;
    void init(){
        for(register int i=2;i<=n;i++){
            if(!vis[i]){
                prime[++cnt]=i;
                phi[i]=i-1;
            }
            for(register int j=1;j<=cnt&&i*prime[j]<=n;j++){
                int k=i*prime[j];
                vis[k]=1;
                if(i%prime[j]==0){
                    phi[k]=phi[i]*prime[j];
                    break;
                }
                else{
                    phi[k]=phi[i]*(prime[j]-1);
                }
            }
            phi[i]=phi[i-1]+(phi[i]<<1);
        }
    }
    int main(){
        scanf("%d",&n);
        init();
        for(register int i=1;i<=cnt;i++){
            sum+=phi[n/prime[i]]+1;
        }
        printf("%lld",sum);
        return 0;
    }

    2.莫比乌斯反演
    当1<=x<=n,1<=y<=m时,欧拉函数的求法就不管用了,这时我们可以用莫比乌斯反演来简化计算。
    我们设

    f(n)=d|n[gcd(x,y)==d]

    F(n)=d|nf(d)

    根据莫比乌斯反演定理可得
    f(n)=d|nμ(n/d)F(d)

    F(d)的值可以通过它的定义发现
    F(d)=(n/d)(n/d)

    f(n)=d|nμ(n/d)((n/d)(n/d))

    枚举质数,暴力累计答案即可。
    (此方法在洛谷70,TLE*3,在bzojAC)
    此题升级版:洛谷P3455

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define ll long long
    using namespace std;
    int mu[10000001];
    int cnt;
    bool vis[10000001];
    int prime[5000001];
    void init(int n){
        mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!vis[i]){
                prime[++cnt]=i;
                mu[i]=-1;
            }
            for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
                int k=i*prime[j];
                vis[k]=1;
                if(i%prime[j]){
                    mu[k]=-mu[i];
                }
                else{
                    mu[k]=0;
                    break;
                }
            }
        }
    }
    int main(){
        ll n;
        scanf("%lld",&n);
        init(n);
        ll ans=0;
        for(ll i=1;i<=cnt;i++){
            ll lim=n/prime[i];
            for(ll j=1;j<=lim;j++){
                ans+=mu[j]*((lim)/j)*((lim)/j);
            }
        }
        printf("%lld",ans);
        return 0;
    }

    考虑优化。
    我不会推公式,就借dalao的公式一用吧(滑稽)
    这里写图片描述
    然后就可以分块搞了。。。
    (其实跑的还挺快的,时间和欧拉几乎相同)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define ll long long
    using namespace std;
    int mu[10000001];
    int cnt;
    bool vis[10000001];
    int prime[5000001];
    void init(int n){
        mu[1]=1;
        for(int i=2;i<=n;++i){
            if(!vis[i]){
                prime[++cnt]=i;
                mu[i]=-1;
            }
            for(int j=1;j<=cnt&&i*prime[j]<=n;++j){
                int k=i*prime[j];
                vis[k]=1;
                if(i%prime[j]){
                    mu[k]=-mu[i];
                }
                else{
                    mu[k]=0;
                    break;
                }
            }
            mu[i]+=mu[i-1];
        }
    }
    int main(){
        ll n;
        scanf("%lld",&n);
        init(n);
        ll ans=0;
        for(ll k=1;k<=cnt;++k){
            ll m=n/prime[k];
            ll j;
            for(ll i=1;i<=m;i=j+1){
                ll mul=m/i;
                j=min(m,m/mul);
                ans+=mul*mul*(mu[j]-mu[i-1]);
            }
        }
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    用java实现的微信公众号爬虫
    装饰模式
    输入一个数,查询该数是否为素数
    Machine-learning-DecisionTree
    Circles of Waiting
    GRE阅读
    云数据库POLARDB产品解读之二:如何做到高性价比
    奉上一份云上数据安全保护指南
    从双十一看阿里云安全的“创世纪”——采访阿里云安全掌门人肖力有感
    阿里云移动研发平台EMAS,是如何连续5年安全护航双11的?
  • 原文地址:https://www.cnblogs.com/stone41123/p/7581263.html
Copyright © 2011-2022 走看看