欧拉函数

运用线性筛

//若p是x的约数,则E(x*p)=E(x)*p.
//若p不是x的约数,则E(x*p)=E(x)*E(p)=E(x)*(p-1). 
#include<iostream>  
#include<string>  
#include<cstring>  
using namespace std;  
const int MAXN=3000001;  
int prime[MAXN];//保存素数   
bool vis[MAXN];//初始化   
int phi[MAXN];//欧拉函数   
void Prime(int n)  
{  
    int cnt=0;  
    memset(vis,0,sizeof(vis));  
    for(int i=2;i<n;i++)  
    {  
        if(!vis[i])  
        {  
            prime[cnt++]=i;  
            phi[i]=i-1;// if p is prime,then phi[i]=i-1  
        }  
        for(int j=0;j<cnt&&i*prime[j]<n;j++)  
        {  
            __int64 k=i*prime[j];  
            vis[k]=1;  
            if(i%prime[j]==0)//关键   
            {  
                phi[k]=phi[i]*prime[j];  
                break;  
            }  
            else  
            phi[k]=phi[i]*(prime[j]-1);  

        }  
    }  
}  
int main()  
{  
    int a,b;  
    Prime(3000000);  
    while(cin>>a>>b)  
    {  
        __int64 ans=0;  
        for(int i=a;i<=b;i++)  
        ans+=phi[i];  
        cout<<ans<<endl;  
    }  
}  

例题:HDU3501
题目大意:给你一个N,求小于等于N的不互质的数的总和。
欧拉公式的引伸:小于或等于n的数中,与n互质的数的总和为:φ(x) * x / 2。(n>1)
所以:res = n*(n-1)/2-n - phi[x]*x/2。

#include <iostream>
#include <cstdio>
using namespace std;

typedef long long LL;

int eular(LL n)     //欧拉函数
{
    int i, ans = n;
    for(i = 2; i * i <= n; i++)
    {
        if(n%i == 0)
        {
            ans -= ans/i;
            while(n%i == 0)
                n /= i;
        }
    }
    if(n > 1) ans -= ans/n;

    return ans;
}

int main()
{
    LL n, ans;
    while(scanf("%lld", &n), n)
    {
        ans = n * (n+1) / 2 - n;    //总和
        ans -= eular(n) * n / 2;    //减去互质的总和公式
        ans %= 1000000007;          //再取模
        printf("%lld\n", ans);
    }

    return 0;
}
posted @ 2018-01-05 16:45  Menteur_hxy  阅读(147)  评论(0编辑  收藏  举报