/* * pku22480.cpp * * Created on: 2010-8-6 * Author: hduacm * 这是用Eclipse 写的,刚开始用这个写c++ 觉得有些东西很陌生,还有就是是在Lunix 系统写的, * 就觉得更不顺手了,看来Eclipse 是很强大的。我想应该装个这样的系统玩玩了 * 数论的题目总是无从下手,很多定理都不知道,怎么作呢?? * * 别人的分析: * 只能考虑 对于gcd(M,N)=i 有Ci个M满足此式 答案便是∑(Ci*i) gcd(M,N)=i <=> gcd(M/i,N/i)=1 而求gcd(M/i,N/i)=1 有多少个M/i满足 这便是欧拉函数Phi()的定义 所以就转化为了求Phi(N/i) 枚举每个 M|N 求出Phi(N/i) 答案便是 ∑(Phi(N/i)*i) 那么如何枚举每个 M|N 呢? 很简单 枚举1到sqrt(N)的所有整数,所有的约数便是 j|N (N/j)|N 这个题目看了解题报告还是么有办法阿。。。 http://acm.hdu.edu.cn/showproblem.php?pid=3508 */ #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; const int N = 50005; bool hash[N]; inline int oula(int n) { int temp = n; int sum = n; bool flag; for(int i = 2; i <= (int)(sqrt(1.0 * n)) ; i++) { if(hash[i]) continue; flag = false; if(i > n || temp == 1) break; while(1) { if(temp % i != 0 || temp == 1) break; flag = true; temp /= i; } if(flag) sum = sum / i * (i - 1); } if(temp > 1) sum = sum / temp * (temp - 1); return sum; } inline void prime() { memset(hash, false, sizeof(hash)); for(int i = 2; i < N / 2; i ++) if(!hash[i]) for(int j = i + i; j < N; j += i) hash[j] = true; } int main() { int n; prime(); while( scanf("%d", &n) != EOF ) { long long sum = 0; for(int i = 1; i <= (int)(sqrt(1.0 * n)); i++) { if(n % i != 0) continue; sum += (n / i) * (oula(i)); // 注意约数是成对出现的 if(i * i != n) sum += i * (oula(n / i)); } printf("%lld/n", sum); } }