星星之火

[luogu P2586] GCD 解题报告 (莫比乌斯反演|欧拉函数)

题目链接:https://www.luogu.org/problemnew/show/P2568#sub

题目大意:

计算$\sum_{x=1}^n\sum_{y=1}^n [gcd(x,y)==prime]$

题解:

解法一:莫比乌斯反演套路题

其实这样就可以了,但是还可以优化一下子

​T=dp

整除分块就好了,其实这就和 yy的gcd 一样了

解法二:欧拉函数

考虑上面的第一个式子可以化简成

tot是n以内质数的数量

这是因为考虑到每次都两次计算了​$\varphi(1)$

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;

const int N=1e7+15;
int n,tot;
ll ans;
int prime[5000000];
ll phi[N];
bool vis[N];
void get_phi()
{
    phi[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!vis[i]) {phi[i]=i-1;prime[++tot]=i;}
        for (int j=1;j<=tot&&i*prime[j]<=n;j++)
        {
            vis[i*prime[j]]=1;
            if (i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1);
            else 
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
        }
    }
    for (int i=2;i<=n;i++) phi[i]=phi[i-1]+phi[i];
}
int main()
{
    scanf("%d",&n);
    get_phi();
    //for (int i=1;i<=n;i++) printf("%d ",phi[i]);
    for (int i=1;i<=tot;i++)
    {
        ans+=phi[n/prime[i]];
    }
    printf("%lld\n",ans*2-tot);
    return 0;
}

 

posted @ 2018-09-14 14:43  星星之火OIer  阅读(179)  评论(0编辑  收藏  举报