bzoj 2705: [SDOI2012]Longge的问题

2705: [SDOI2012]Longge的问题

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 1978  Solved: 1237
[Submit][Status][Discuss]

Description

Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。

Input

一个整数,为N。

Output

一个整数,为所求的答案。

Sample Input

6

Sample Output

15

HINT

 

【数据范围】

对于60%的数据,0<N<=2^16。

对于100%的数据,0<N<=2^32。

 题解:因为1到n中的数与n的最大公约数只可能是n的因子,所以我们找到所有与n有相同因子k的数的个数然后sum+=k*s[k](s[k]是指与n有相同最大公约数k的数的个数)因为gcd(m,n)=k,所以gcd(m/k,n/k)=1,这样所有与n/k最大公约数为1的数就是与n最大公约数为k的数则s[k]=euler(n/k),同时s[n/k]=euler(k);

#include<stdio.h>
#include<string.h>
#include<cstdio> 
#include<string>
#include<math.h>
#include<algorithm>
#define LL long long
#define PI atan(1.0)*4
#define DD double
#define MAX 2002000
#define mod 100
#define dian 1.000000011
#define INF 0x3f3f3f
using namespace std;
int el(int x)
{
	int ans=x;
	int i,j;
	for(i=2;i*i<=x;i++)
	{
		if(x%i==0)
		    ans=ans/i*(i-1);
		while(x%i==0)
		    x/=i;
	}
	if(x>1)
	   ans=ans/x*(x-1);
	return ans;
}
LL s[MAX]; 
int main()
{
    LL n,m,j,i,t,k;
    while(scanf("%lld",&n)!=EOF)
    {
        LL sum=0;
        k=0;
    	for(i=1;i<=sqrt(n);i++)
    	{
    		if(n%i==0)
    		{
    			sum+=el(n/i)*i;
    			if(i*i<n)
    			    sum+=(n/i)*el(i);
    			//因为i只能取到n的平方根出,所以平方根后n的因子取不到
				//这句是求平方根后与n的公约数 
    		}
    	}
    	printf("%lld\n",sum);
    }
	return 0;
}

  

posted @ 2016-03-17 21:05  非我非非我  阅读(372)  评论(0编辑  收藏  举报