• BZOJ 2818 Gcd 线性欧拉


    题意:链接

    方法:线性欧拉

    解析:

    首先列一下表达式

    gcd(x,y)=z(z是素数而且x,y<=n).

    然后我们能够得到什么呢?

    gcd(x/z,y/z)=1;

    最好还是令y>=x

    则能够得到我们要的答案就是max(y/z)i=1phi(i)

    而max(y/z)就是max(n/z)。

    所以仅仅须要枚举一下质数z随便搞一下就好了,最好用前缀和记录

    HINT:前缀和写树状数组的都是(*)

    代码:

    正常人做法1.1s

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define N 10000010
    using namespace std;
    typedef long long ll;
    int n,tot;
    int prime[N];
    int phi[N];
    ll sum[N];
    int f[N];
    void sieve()
    {
        phi[1]=1;
        sum[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(!f[i])
            {
                prime[++tot]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=tot,i*prime[j]<=n;j++)
            {
                f[i*prime[j]]=1;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }else
                {
                    phi[i*prime[j]]=phi[i]*phi[prime[j]];
                }
            }
            sum[i]=sum[i-1]+phi[i];
        }
    }
    int main()
    {
        scanf("%d",&n);
        sieve();
        ll print=0;
        for(int i=1;i<=tot;i++)
        {
            int up=n/prime[i];
            print+=sum[up];
        }
        printf("%lld
    ",print*2-tot);
    }

    树状数组4.8s

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define N 10000010
    using namespace std;
    typedef long long ll;
    int n,tot;
    int prime[N];
    int phi[N];
    ll sum[N];
    int f[N];
    int lowbit(int x){return x&(-x);}
    void update(int x,int p)
    {
        while(x<=n)
        {
            sum[x]+=p;
            x+=lowbit(x);
        }
    }
    ll getsum(int x)
    {
        ll ret=0;
        while(x)
        {
            ret+=sum[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void sieve()
    {
        phi[1]=1;
        update(1,1);
        for(int i=2;i<=n;i++)
        {
            if(!f[i])
            {
                prime[++tot]=i;
                phi[i]=i-1;
                update(i,phi[i]);
            }
            for(int j=1;j<=tot,i*prime[j]<=n;j++)
            {
                f[i*prime[j]]=1;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    update(i*prime[j],phi[i*prime[j]]);
                    break;
                }else
                {
                    phi[i*prime[j]]=phi[i]*phi[prime[j]];
                    update(i*prime[j],phi[i*prime[j]]);
                }
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        sieve();
        ll print=0;
        for(int i=1;i<=tot;i++)
        {
            int up=n/prime[i];
            print+=getsum(up);
        }
        printf("%lld
    ",print*2-tot);
    }
  • 相关阅读:
    MongoDB学习
    Linux 硬盘分区、分区、删除分区、格式化、挂载、卸载
    openstack中数据库连接数太多--pymysql.err.OperationalError,1040, u'Too many connections'
    openstack各服务端口使用情况
    linux常用命令
    云计算---OpenStack Neutron详解
    shell---数据流重定向
    云计算---openstack创建虚拟机过程
    SpringMvc面试题
    Linux 本机/异机文件对比
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7256971.html
Copyright © 2020-2023  润新知