The Euler function

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


Problem Description
The Euler function phi is an important kind of function in number theory, (n) represents the amount of the numbers which are smaller than n and coprime to n, and this function has a lot of beautiful characteristics. Here comes a very easy question: suppose you are given 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
 

Source


思路:
题目意思大体就是,给了你欧拉函数的定义,就是不超过这个数的和它互质的数的个数。然后让你求从a到b的各个数的欧拉函数之和。
初始的想法是用笨方法,对每个数进行素数查找并判断(从2到根号n的那种方法)但是这种方法太原始了,会超时。
后来引进来一种素数表的方法,比如现在我要求4到121的欧拉函数之和,你就直接找121以下的所有素数,那么它下边的每个数的素数都会包含在这里面。然后再运用数论的知识:
     1、素数p的欧拉函数是p-1,即 φ(p)=p-1。特别地,φ(1)=1。
     2、p的k次方的欧拉函数是(p-1)*p的k-1次方,即 φ(p^k)=(p-1)*p^(k-1)。
     3、积性函数, φ(mn)=φ(m)*φ(n)
     4、埃式筛法(快速寻找n以内的质数)和质因数分解 (埃式筛法和质因数分解还有欧拉函数模板等内容请详情查看另一篇文章。)
这样的话,题目就可以用一个int数组来保存1-n中每个数的函数欧拉函数,再求和。


代码:

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

int phi[3000000];
int dive[3000000];

int main()
{
    int a,b;
    while(cin>>a>>b)
    {
    long long sum=0;
    for(int i=1;i<=b;i++)
    {
        phi[i]=i;
    }
    for(int i=2;i*i<=b;++i)
    {
        if(phi[i]==i)
        {
            for(int j=i*i;j<=b;j+=i)
            {
               phi[j]=i;
            }
        }
    }
    dive[1]=1;
    for(int i=2;i<=b;++i)
    {
        dive[i]=dive[i/phi[i]];
        if((i/phi[i])%phi[i]==0)
        {
            dive[i]*=phi[i];
        }
        else
        {
            dive[i]*=phi[i]-1;
        }
    }
    for(int i=a;i<=b;i++)
    {
        sum+=1LL*dive[i];
    }
    cout<<sum<<endl;

    }
}