线性求欧拉函数值和筛选素数

2818: Gcd

题目

给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的

数对(x,y)有多少对. 1<=N<=10^7

算法:

求解 g = Gcd(x,y)为素数,转换问题成x/g,y/g互质。所以,只要求出[1,N/pi]内互质的对数(pi为1....N之间的素数)。枚举pi就可以了。而这里就可以用到线性的欧拉求解,普通欧拉为O(nlognlogn)。

/*

线性素数加欧拉筛法O(N)

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

   其实就是一个转化问题,求gcd(x, y) = k, 1 <= x, y <= n的对数等于:
求gcd(x, y) = 1, 1 <= x, y <= n/k的对数。(在[1,n/k]存在多少个有序对(x,y)使得互质)
那么接下来我们就只要枚举每个素数k=prime[i]了,然后用到欧拉函数就可以求出来了,
Σ( 2*Σ( phi[n/prime[i]] ) - 1 )。

N < 10^7
欧拉函数:phi[n]表示1~n内有多少个数与n互质

*/

typedef long long LL;
const int MAXN  = 10000000 + 10;

int top,primes[700000];
LL phi[MAXN];
int n;

//线性筛欧拉值和素数表
void phi_primes(){
    top = 0; phi[1] = 1;
    for(int i = 2;i <= n;++i){
        if(!phi[i]){
            primes[top++] = i;
            phi[i] = i - 1;
        }
        for(int j = 0;j < top&&i*primes[j] <= n;++j){
            if(i%primes[j])
                phi[i*primes[j]] = phi[i]*(primes[j] - 1);
            else {phi[i*primes[j]] = phi[i]*primes[j]; break;}
        }
    }
}

int main()
{
      scanf("%d",&n);
      phi_primes();

       for(int i = 2;i <= n;++i) phi[i] += phi[i-1];  //1...i内互质的总数 

        LL ans = 0;
        for(int i = 0;i < top&&primes[i] <= n;++i){
            ans += (phi[n/primes[i]] << 1)-1;     //除去素数多算的一次
        }
        printf("%lld\n",ans);
    return 0;
}
时间: 2024-10-17 03:58:47

线性求欧拉函数值和筛选素数的相关文章

线性求欧拉函数

我们都知道欧拉筛又称线性筛,能在O(n)的时间复杂度内筛出n以内的所有质数,而我们只要在线性筛的代码上改良一下就能求出n以内所有数的欧拉函数了.筛质数时,设外层在枚举i,内层枚举到prime[j],这时有两种情况: i%prime[j]不为0,也就是说,i与j互质,根据欧拉函数的积性可得phi[ i * prime[j] ]=phi[ i ]*phi[ prime[j] ]而这些是前面求出来的,可以直接拿来推. i%prime[j]为0,也就是说,i内有一个质因子是prime[j],不过没有关系

欧拉筛素数+求欧拉函数

线性筛法 prime记录素数,num_prime素数下标 它们保证每个合数只会被它的最小质因数筛去 a[0]=a[1]=1; for(int i=2;i<=n;i++) { if(!a[i]) prime[num_prime++]=i; for(int j=0;j<num_prime&&i*prime[j]<=n;j++) { a[i*prime[j]]=1; if(!(i%prime[j])) break; } } } 欧拉函数 是 积性函数:对于任意互质的整数a和b有

hdu2824 The Euler function 筛选法求欧拉函数模板题

//求a , b范围内的所有的欧拉函数 //筛选法求欧拉函数模板题 #include<cstdio> #include<cstring> #include<iostream> using namespace std ; const int maxn = 3000010 ; typedef __int64 ll ; int e[maxn] ; int a ,  b ; void Euler() { int i,j; for (i=1;i<maxn;i++) e[i]

poj 2478 Farey Sequence(基于素数筛法求欧拉函数)

http://poj.org/problem?id=2478 求欧拉函数的模板. 初涉欧拉函数,先学一学它基本的性质. 1.欧拉函数是求小于n且和n互质(包括1)的正整数的个数.记为φ(n). 2.欧拉定理:若a与n互质,那么有a^φ(n) ≡ 1(mod n),经常用于求幂的模. 3.若p是一个质数,那么φ(p) = p-1,注意φ(1) = 1. 4.欧拉函数是积性函数: 若m与n互质,那么φ(nm) = φ(n) * φ(m). 若n = p^k且p为质数,那么φ(n) = p^k - p

求逆元的四种算法(拓欧费马小线性推欧拉)

求逆元的四种算法 拓展欧几里得算法求逆元 上一篇博客中已经讲过拓展欧几里得算法,并且讲解了求逆元的原理.这里只列出代码 在要求逆元的数与p互质时使用 代码 //扩展欧几里得定理 int ex_gcd(int a,int b,int& x,int& y) { if(b==0) { x=1; y=0; return a; } int ans = ex_gcd(b,a%b,x,y); int tmp = x; x = y; y = tmp-a/b*y; return ans; } int cal

POJ 2478 Farey Sequence 筛选法求欧拉函数

题目来源:POJ 2478 Farey Sequence 题意:输入n 求 phi(2)+phi(3)+phi(4)+...+phi(n) 思路:用类似筛法的方式计算phi(1), phi(2), ..., phi(n) 再求前缀和 #include <cstdio> #include <cstring> #include <cmath> //欧拉phi函数 const int maxn = 1000010; typedef long long LL; int eule

欧拉函数值求解与应用

欧拉函数简介: 欧拉函数只是工具:提供1到N中与N互质的数 定义和简单性质 欧拉函数在OI中是个非常重要的东西,不知道的话会吃大亏的. 欧拉函数用希腊字母φ表示,φ(N)表示N的欧拉函数. 对φ(N)的值,我们可以通俗地理解为小于N且与N互质的数的个数(包含1). 欧拉函数的一些性质: 1.对于素数p, φ(p)=p-1,对于对两个素数p,q φ(pq)=pq-1 欧拉函数是积性函数,但不是完全积性函数. 证明: 函数的积性即:若m,n互质,则φ(mn)=φ(m)φ(n).由"m,n互质&quo

【poj2478-Farey Sequence】递推求欧拉函数-欧拉函数的几个性质和推论

http://poj.org/problem?id=2478 题意:给定一个数x,求<=x的数的欧拉函数值的和.(x<=10^6) 题解:数据范围比较大,像poj1248一样的做法是不可行的了. 首先我们要了解欧拉函数的几个性质和推论:(今天跟好基友Konjak魔芋讨论了好久..) 推论(一): phi(p^k)=(p-1)*p^(k-1) 证明: 令n=p^k,小于等于n的正整数数中,所有p的倍数共有p^k /p = p^(k-1)个. 1~n出去p的倍数,所以phi(n)= n -  p^

POJ2478_Farey Sequence【快速求欧拉函数】

Farey Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12377 Accepted: 4808 Description The Farey Sequence Fn for any integer n with n >= 2 is the set of irreducible rational numbers a/b with 0 < a < b <= n and gcd(a,b) = 1