题目链接: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;
}
}