洛谷题单指南-进阶数论-P2568 GCD

原题链接:https://www.luogu.com.cn/problem/P2568

题意解读:题意很简单明了,求  且  为素数的数对  有多少对。

解题思路:

推公式!

根据题意要求的是所有gcd是素数的数对数量,那么可以从素数出发,看素数是多少个数对的gcd

推出原始公式:

image

将gcd=d调整为gcd=1后公式变形为:

image

减1是因为要排除掉gcd(1,1)=1的影响,上面的式子gcd(i,j)=d不会有影响

对i从1~n/d,j从1~n/d的数对进行去重,然后用2倍计算:

image

不难发现:

image就是i以内与i互质的数的个数,即欧拉函数Φ(i)

因此有:

image

n以内的素数,1~n/d的欧拉函数Φ(i)都可以在欧拉筛的过程中求得,最后按公式计算结果即可。

image可以用前缀和来优化。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 10000005;
int p[N], cnt;
bool vis[N];
long long phi[N], sum[N];
int n;
long long ans;

int main()
{
    cin >> n;
    phi[1] = 1;
    for(int i = 2; i <= n; i++)
    {
        if(!vis[i])
        {
            p[++cnt] = i;
            phi[i] = i - 1;
        }
        for(int j = 1; j <= cnt; j++)
        {
            if(i * p[j] > n) break;
            vis[i * p[j]] = true;
            if(i % p[j] == 0)
            {
                phi[i * p[j]] = phi[i] * p[j];
                break;
            }
            else
            {
                phi[i * p[j]] = phi[i] * (p[j] - 1);
            }
        }
    }

    for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + phi[i];

    for(int d = 1; d <= cnt; d++)
    {
        ans += 2 * sum[n / p[d]] - 1;
    }

    cout << ans;
    return 0;
}

 

posted @ 2025-09-30 10:15  hackerchef  阅读(9)  评论(0)    收藏  举报