題幹
T組詢問,每組給出一個n,求:
題解
先進行變形:
枚舉gcd(i, n),有:
顯然d與n/d是等價的,於是:
即我們要求小於i且與i互素的所有自然數之和。有結論:
由於本人數學功底不好所以就不證明了。直接利用結論:預處理phi函數,對於n枚舉因數即可。
代碼
(不要隨便看代碼,不要隨便看代碼,不要隨便看代碼。因爲很重要所以說三遍。)
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
//Global Variables & Definitions
#define LL long long
#define MAXN 1000010
int T, _n;
//End Global Variables & Definitions
//Number Theory
int p[MAXN];
int vis[MAXN];
int ph[MAXN];
int pcnt = 0;
void init_p() {
ph[1] = 1; ph[2] = 1;
LL temp;
for(int i = 2;i < MAXN;++i) {
if(!vis[i]) { p[pcnt] = i; ph[i] = i - 1; ++pcnt; }
for(int j = 0;j < pcnt && (temp = (LL)p[j] * i) < MAXN;++j) {
vis[temp] = 1;
if(i % p[j] == 0) { ph[temp] = ph[i] * p[j]; break; }
else ph[temp] = ph[i] * (p[j] - 1);
}
}
//for(int i = 1;i <= 20;++i) printf("phi[%d] = %d\n", i, ph[i]);
}
inline LL phi(int n) {
return ph[n];
}
LL solve(int n) {
LL ans = 0ll;
int half = (int) (sqrt(n) + 0.01);
if(half * half == n) { ans += phi(half) * half / 2; --half; }
ans += 1; //for 1
ans += phi(n) * n / 2;
for(int i = 2;i <= half;++i)
if(n % i == 0) {
ans += phi(i) * i / 2;
ans += phi(n / i) * n / i / 2;
}
return ans * n;
}
//End Number Theory
//Main Structure
inline void ir() {
scanf("%d", &T);
init_p();
}
int main() {
ir();
while(T--) {
scanf("%d", &_n);
printf("%lld\n", solve(_n));
}
return 0;
}