zoukankan      html  css  js  c++  java
  • 欧拉函数——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;
    }
  • 相关阅读:
    bzoj2064分裂(dp)
    关于逆元的学习笔记(尚未完成)
    线性基学习笔记
    bzoj2460元素(线性基,贪心)
    CF280C Game on tree(期望dp)
    XJOI contest800
    关闭极域电子教室学生端的各种方法
    大坑!有网,电脑qq登不上去!!
    4.25 ZJOI2017 10AM
    bzoj1621
  • 原文地址:https://www.cnblogs.com/helman/p/11354161.html
Copyright © 2011-2022 走看看