描述
题解
这个题更准确的描述应该是求
F(n)=∑i=1n∑j=1nϕgcd(ϕi,ϕj)
首先我们可以设
s[i]
表示
1∼n
中欧拉函数等于
i
的数有多少个。那么我们可以得到:设
g(d)=∑i=1⌊nd⌋∑j=1⌊nd⌋s[id]∗s[jd][gcd(i,j)=1]
f(d)=∑k=1⌊nd⌋g(kd)
所以
f(d)=∑i=1⌊nd⌋∑j=1⌊nd⌋s[id]∗s[jd]
这里的
f
数组预处理一下即可。
所以由于
F(n)=∑d=1ng(d)∗ϕd=∑d=1nϕd∑i=1⌊nd⌋μi∗f(id)
如此这般,套模版就好了。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 2e6 + 5;
int n, tot;
ll ans;
ll s[MAXN];
ll f[MAXN];
int pri[MAXN];
int phi[MAXN];
int miu[MAXN];
bool vis[MAXN];
void solve()
{
memset(vis, 0, sizeof(vis));
memset(phi, 0, sizeof(phi));
memset(miu, 0, sizeof(miu));
memset(s, 0, sizeof(s));
memset(f, 0, sizeof(f));
ans = tot = 0;
miu[1] = phi[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!vis[i])
{
pri[tot++] =i ;
miu[i] = -1;
phi[i] = i - 1;
}
for (int j = 0, k; j < tot; j++)
{
k = i * pri[j];
if (k > n)
{
break;
}
vis[k] = 1;
if (i % pri[j] == 0)
{
miu[k] = 0;
phi[k] = phi[i] * pri[j];
break;
}
miu[k] = -miu[i];
phi[k] = phi[i] * (pri[j] - 1);
}
}
for (int i = 1; i <= n; i++)
{
s[phi[i]]++;
}
for (int i = 1; i <= n; i++)
{
for (int j = i; j <= n; j += i)
{
f[i] += s[j];
}
}
for (int i = 1; i <= n; i++)
{
f[i] = f[i] * f[i];
}
for (int i = 1; i <= n; i++)
{
if (miu[i] != 0)
{
for (int d = 1; i * d <= n; d++)
{
ans += miu[i] * phi[d] * f[i * d];
}
}
}
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
solve();
printf("%lld\n", ans);
}
return 0;
}