HDOJ 2824 The Euler function (欧拉函数)

来源:互联网 发布:php开发教程视频 编辑:程序博客网 时间:2024/05/16 03:52

The Euler function

Time Limit: 2000/1000 MS(Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7222    Accepted Submission(s): 2999

Problem Description

The Euler function phi is animportant kind of function in number theory, (n) represents the amount of thenumbers which are smaller than n and coprime to n, and this function has a lotof beautiful characteristics. Here comes a very easy question: suppose you aregiven a, b, try to calculate (a)+ (a+1)+....+ (b)

 

 

Input

There are several test cases.Each line has two integers a, b (2<a<b<3000000).

 

 

Output

Output the result of (a)+(a+1)+....+ (b)

 

 

Sample Input

3 100

 

 

Sample Output

3042

题意:(x)代表小于n的数中与n互质的数的个数,给定区间【a,b】,问闭区间内所有(x)值的总和


先给出求欧拉函数值的两个模板:

一:适用于一次运算需要多个数的欧拉函数值时(但数据范围不能太大)(离线方法)

时间复杂度 nloglogn

void euler(){    mst(res,0);    res[1]=1;    for(int i=2;i<maxn;i++)    {        if(!res[i])        {            for(int j=i;j<maxn;j+=i)            {                if(!res[j])                    res[j]=j;                res[j]=res[j]/i*(i-1);            }        }    }}



二:适用于每次运算只需要少数几个数的欧拉函数值(能够求的数的数据范围比方法一大)(在线方法)

时间复杂度:sqrt(n)

int euler(int n){    int res=n,num=n;    for(int i=2; i*i<=num; i++)    {        if(num%i==0)        {            res=res/i*(i-1);            while(num%i==0)                num/=i;        }    }    if(num>1)        res=res/num*(num-1);    return res;}

分析:易知(x)值即为x的欧拉函数值(即phi),可以套用模板,但考虑到【a,b】的范围较大,在线查询肯定会超时,所以我们需要预处理出所要用到的数的phi值,这样累加时还是有O(n)的复杂度,但只要我们在预处理时求个前缀和即可。sigma(phi(i))(a<=i<=b) = sum[b]-sum[a-1]

完整代码
#include <bits/stdc++.h>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<(b);++i)const int maxn = 3000005;const int mod = 200907;#define ll long long#define rush() int t;scanf("%d",&t);while(t--)ll res[maxn];void euler(){    mst(res,0);    res[1]=1;    for(int i=2;i<maxn;i++)          //打表算出每个数的phi值    {        if(!res[i])        {            for(int j=i;j<maxn;j+=i)            {                if(!res[j])                    res[j]=j;                res[j]=res[j]/i*(i-1);            }        }    }    for(int i=2;i<maxn;i++)          //从1到某一个数的phi值的前缀和    {        res[i]+=res[i-1];    }}int main(){    int n,m;    euler();    while(~scanf("%d%d",&n,&m))    {        printf("%I64d\n",res[m]-res[n-1]);    }    return 0;}




                                             
0 0