ACM模版

描述

题解

这个题更准确的描述应该是求

F(n)=i=1nj=1nϕgcd(ϕi,ϕj)
首先我们可以设 s[i] 表示 1n 中欧拉函数等于 i 的数有多少个。那么我们可以得到:
F(n)=d=1ni=1ndj=1ndϕds[id]s[jd][gcd(i,j)=1]
此时,反演可以上了。

g(d)=i=1ndj=1nds[id]s[jd][gcd(i,j)=1]
f(d)=k=1ndg(kd)
所以
f(d)=i=1ndj=1nds[id]s[jd]
这里的 f 数组预处理一下即可。

所以由于

g(d)=i=1ndμif(id)
所以
F(n)=d=1ng(d)ϕd=d=1nϕdi=1ndμif(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;
}