您的位置:首页 > 其它

【bzoj】2705 - [SDOI2012]Longge的问题(欧拉函数)

2016-07-23 16:57 323 查看
点击打开题目

2705: [SDOI2012]Longge的问题

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 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

round1 day1

这道题需要好好的分析一下,首先要列举出 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: