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,输出gcd(1,n)~gcd(n,n)的和;

暴力必定超时,n<=2^32,我们可以换一下思路:当gcd(x,n)=i,同时除i,则变成gcd(x/i,n/i)=1;

转换成了求n/i的质因子的个数,他个个数再乘i即为值,顺便求出i的质因子的个数*(n/i);

最后判断一下n/i和i是否相等(相等的话只取一个即可)

ac:

#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<iostream>  
#include<algorithm>  
using namespace std;  

#define ll long long  
#define INF 0x3f3f3f3f  
#define mod 1000000007
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
//std::ios::sync_with_stdio(false);

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

int main()
{
	ll n;
	while(cin>>n)
	{
		ll ans=0;
		for(ll i=1;i*i<=n;++i)
		{
			if(n%i==0)
			{
				ans=ans+euler(n/i)*i;//结果为i的个数 
				if(i*i<n)
					ans=ans+euler(i)*(n/i);//结果为n/i的个数 
			}
		}
		cout<<ans<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/81475902