• 欧拉函数——HYSBZ


    题目链接

    计算gcd(x,y)为素数的(x,y)有多少对

    首先有一个必要的式子,gcd(x,y)=素数p => gcd(x/p,y/p)=1

    所以若y>x,在确定y的情况下,所有满足与y/p互质的数的个数,即y/p的欧拉函数值

    所以我们可以先筛一遍欧拉函数,并求前缀和,方便之后使用

    这样sum[n/p]=phi[1]+phi[2]+...+phi[y/p]+...+phi[n/p]

    代表你已经求了让y>x时,gcd=p的所有对数

    然后还有x>y的情况,就sum[n/p]*2

    然后还要注意一下phi[1]这个东西

    它表示gcd(p,p)=p,虽然你求phi[p]的时候不会算上它,但是你求的是phi[p/p]

    这里的phi[1]是默认为1的,说明你每个素数都多算了一次

    题目代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    typedef long long LL;
    const int maxn=1e7+7;
    int phi[maxn],prime[maxn];
    LL sum[maxn];
    bool check[maxn];
    int cnt=0;
    void euler(){
        phi[1]=1;
        sum[0]=0;
        sum[1]=1;
        for(int i=2;i<maxn;i++){
            if(!check[i]){
                prime[cnt++]=i;
                phi[i]=i-1;
            }
            for(int j=0;j<cnt&&i*prime[j]<maxn;j++){
                check[i*prime[j]]=true;
                if(i%prime[j])
                    phi[i*prime[j]]=phi[i]*(prime[j]-1);
                else {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
            }
            sum[i]=sum[i-1]+phi[i];
        }
    }
    LL n;
    int main(){
        euler();
        scanf("%lld",&n);
        LL ans=0;
        for(int i=0;i<cnt&&prime[i]<=n;i++){
            ans+=2*sum[n/prime[i]];
            ans--;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    理解JAVA常量池
    java存储位置经典例子
    java通过句柄访问对象
    常用排序算法小结
    String,StringBuffer与StringBuilder的区别
    BGP
    BGP
    python编码问题实例
    从一段代码学习二叉树
    二叉树学习笔记--先序遍历
  • 原文地址:https://www.cnblogs.com/helman/p/11354161.html
Copyright © 2020-2023  润新知