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。
题解
求 $$sum_{i = 1}^N gcd(i, N)$$
用惯用的套路我们枚举 $N$ 的因子 $$sum_{d mid N} d cdot sum_{i = 1}^{ frac{N}{d} } left[gcd left( frac{N}{d} , i ight) = 1 ight]$$
化简为 $$sum_{d mid N} d cdot varphi left( frac{N}{d} ight)$$
欧拉函数直接用 $varphi(n) = n cdot prod_{i = 1}^k left(1-frac{1}{p_i} ight)$ 来求。
1 //It is made by Awson on 2018.1.12 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define Max(a, b) ((a) > (b) ? (a) : (b)) 17 #define Min(a, b) ((a) < (b) ? (a) : (b)) 18 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) 19 using namespace std; 20 void read(LL &x) { 21 char ch; bool flag = 0; 22 for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); 23 for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); 24 x *= 1-2*flag; 25 } 26 void write(LL x) { 27 if (x > 9) write(x/10); 28 putchar(x%10+48); 29 } 30 31 LL n, m, ans; 32 33 LL phi(LL x) { 34 LL ans = x; 35 for (LL i = 2; i <= m; i++) { 36 if (x%i) continue; 37 ans = ans*(i-1)/i; 38 while (!(x%i)) x /= i; 39 } 40 if (x > 1) ans = ans*(x-1)/x; 41 return ans; 42 } 43 void work() { 44 read(n); m = sqrt(n); 45 for (LL i = 1; i <= m; i++) { 46 if (n%i) continue; 47 ans += i*phi(n/i); 48 if (i*i < n) ans += n/i*phi(i); 49 } 50 write(ans); 51 } 52 int main() { 53 work(); 54 return 0; 55 }