码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-10-31 20:45:54      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   ar   for   sp   on   2014   问题   

                             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;
}


 

 

 

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

标签:style   blog   http   ar   for   sp   on   2014   问题   

原文地址:http://blog.csdn.net/zhongshijunacm/article/details/40659287

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!