POJ2480——Longge's problem(数论,欧拉函数d)

来源:互联网 发布:java高并发编程实战 编辑:程序博客网 时间:2024/06/07 19:31

题目:

Longge's problem
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 8050 Accepted: 2666

Description

Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N. 

"Oh, I know, I know!" Longge shouts! But do you know? Please solve it. 

Input

Input contain several test case. 
A number N per line. 

Output

For each N, output ,∑gcd(i, N) 1<=i <=N, a line

Sample Input

26

Sample Output

315

大意:就是求[1,n]的整数和n的最大公约数的和

思路:肯定不能暴力。区间是[1,n],数是n,马上就想到欧拉函数。怎么联系起来?欧拉函数是求互质的数的个数。比如如果n能整除2,那么与n最大公约数为2的数的个数为区间[1,n/2]里头与n/2互质的数的个数。那么和就是phi[n/2]*2。

怎么降低复杂度呢?还是拿2举例子。n/2肯定也是n的约数,那么再加上phi[2]*n/2即可。

代码如下


#include <cmath>#include <cstring>#include <cstdio>#include <vector>#include <string>#include <algorithm>#include <string>#include <set>#include <cmath>using namespace std;typedef long long ll;const int Max=100010;ll p[Max];bool is_prime[Max];ll euler(ll n){    ll res=n,a=n;    for(int i=0;p[i]*p[i]<=a;i++){        if(a%p[i]==0){            res=res/p[i]*(p[i]-1);            while(a%p[i]==0) a/=p[i];        }    }    if(a>1) res=res/a*(a-1);    return res;}int main(){    ll n;    int k=0;    for(int i=0;i<Max;i++)        is_prime[i]=true;    for(int i=2;i<Max;i++)    {        if(is_prime[i])        {            for(int j=2*i;j<Max;j+=i)                is_prime[j]=false;            p[k++]=i;        }    }    while(scanf("%lld",&n)!=EOF)    {        ll sq=(int)sqrt((double)n);        ll ans=0;        for(int i=1;i<=sq;i++)        {            if(i*i==n)            {                ans+=euler(i)*i;            }            else if(n%i==0)            {                long long s=n/i;                ans+=euler(s)*i+euler(i)*s;            }        }        printf("%lld\n",ans);    }    return 0;}














0 0
原创粉丝点击