2705: [SDOI2012]Longge的问题
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 2331 Solved: 1416
[ 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。
Source
这道题需要好好的分析一下,首先要列举出 n 的所有因子,然后对每一个因子 k 要求 GCD(i , n)== k ,求多少个 i 的问题了,但是这个 i 当然不能 for 循环遍历,把 i , k 都除以一个 k (因为他们都有共同的因子 k ),GCD(i / k ,n / k)== 1 ,这就说明两个数这么一变是互质的,那就等于求 n / k 的欧拉函数值,然后乘 k 就行了。
这时候遍历因子的时候有两点需要注意:
①只需要从1到sqrt(n)就行了,另一个因子是对称的(n / i)。
②如果sqrt(n)是整数,那么这个因子只能算一次,不能算对称了(对称还是它自己)
代码如下:
#include <cstdio>
int Eular(int n)
{
int ans = n;
for (int i = 2 ; i * i <= n ; i++)
{
if (n % i == 0)
{
ans -= ans / i;
while (n % i == 0)
n /= i;
}
}
if (n > 1)
ans -= ans / n;
return ans;
}
int main()
{
long long n;
scanf ("%lld",&n);
long long ans = 0;
int i;
for (i = 1 ; i * i < n ; i++)
{
if (n % i == 0)
ans += i * (long long)Eular(n/i) + n/i * (long long)Eular(i); //对称的两个因子
}
if (i * i == n && n % i == 0) //这个因子只能算一遍
ans += i * Eular(i);
printf ("%lld\n",ans);
return 0;
}