【poj】 2480 Longge’s problem (欧拉函数)
【题目链接】http://poj.org/problem?id=2480
题目
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
2
6
Sample Output
3
15
题目大意
求小于等于n的所有正整数与n的最大公因数之和,即∑gcd(i, N) 1<=i <=N
背景知识
欧拉函数
对正整数n,欧拉函数( phi(n) )是小于n的正整数中与n互质的数的数目(φ(1)=1)。
解题思路
先打表找规律,发现对于一个n,最大公因子相同的项很多,于是考虑从因子角度来求,最大公因数为1的项的数量显然为phi(n),对于某个最大公因子为d的i来说,gcd(i,n)=d,即gcd(i/d,n/d)=1,所有与n的最大公因子为d的元素的数量为phi(n/d),(ps:如果从小到大扫一遍,i==d时就能将最大公因子为d的项全部解决掉)
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<math.h>
#include<limits.h>
#include<stack>
#include<queue>
#define LL long long
#define maxn 50010//数据为2^31,预处理因数到5e4即可;
using namespace std;
LL prime[maxn];
LL pr[maxn]={0};//质数
void _prime()
{
LL k=0;
for(LL i=2;i<maxn;i++)
{//printf("%lld ",i);
if(prime[i]==0) pr[k++]=i;
for(LL j=0;j<k&&pr[j]*i<maxn;j++)
{
prime[pr[j]*i]=1;
if(i%pr[j]==0) break;
}
//printf("pr[%lld]=%lld ",k-1,pr[k-1]);
}
return ;
}
LL phi(LL n)//欧拉函数
{
LL ans=n;
for(int i=0;pr[i]*pr[i]<=n;i++)
{
if(n%pr[i]==0)
{
LL x=pr[i];
while(n%x==0)
n/=x;
ans=ans/pr[i]*(pr[i]-1);
}
if(n==1) break;
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
int main()
{
_prime();
LL n,ans,i,nn;
while(cin>>n)
{
nn=n;
ans=n+phi(n);
for(i=2;i*i<n;i++)
{
if(n%i==0)
{
ans += i * phi(n/i) ;//最大公因数为i的情况;
ans += n/i * phi(i) ;
}
}
if(i*i==n)//此时i和n/i是同一个数,只能算一次;
{
ans+=i*phi(i);
}
cout<<ans<<endl;
}
return 0;
}