題意大概是:給定一個N,求出sigma(lcm(i,n))其中(1<=i<=n)
推波式子:
然後這個我們可以O(N)預處理歐拉函數,然後每次詢問根號N,當然這題是存在詢問O(1)的算法,有興趣的讀者可以思考。
附上代碼:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXX = 1000005;
int n, N = MAXX - 5, i, j, cnt, prim[MAXX], phi[MAXX], T;
long long ans;
bool f[MAXX];
inline int get()
{
char c;
while ((c = getchar()) < 48 || c > 57);
int res = c - 48;
while ((c = getchar()) >= 48 && c <= 57)
res = res * 10 + c - 48;
return res;
}
int main()
{
phi[1] = 1;
for(i = 2; i <= N; i ++)
{
if (!f[i])
{
phi[i] = i - 1;
prim[++cnt] = i;
}
for(j = 1; j <= cnt && i * prim[j] <= N; j ++)
{
f[prim[j] * i] = 1;
if (i % prim[j]) phi[i * prim[j]] = phi[i] * (prim[j] - 1);
else {phi[i * prim[j]] = phi[i] * prim[j]; break;}
}
}
cin >> T;
for(i = 1; i <= T; i ++)
{
n = get();
ans = 1;
int nn = sqrt(n);
for(j = 2; j <= nn; j ++)
if (!(n % j))
{
int ot = n / j;
ans += (phi[j] * (long long)j) >> 1;
if (ot != j) ans += (phi[ot] * (long long)ot) >> 1;
}
ans += (phi[n] * (long long)n) >> 1;
printf("%lld\n", ans * n);
}
}