码迷,mamicode.com
首页 > 其他好文 > 详细

P2568 GCD

时间:2019-10-05 20:35:25      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:code   gcd   name   register   int   mat   solution   namespace   莫比乌斯反演   

\(Description\)

给定\(n\),求\(1<=x,y<=n\)满足\(gcd(x,y)=p\)(其中\(p\)为质数)的\((x,y)\)有多少对

\(Solution\)

乍一看是莫比乌斯反演,虽然我不会莫比乌斯反演
其实这道题是简单的筛法+欧拉函数
\(ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^n[gcd(i,j)==p]\)
\(gcd\)常用技巧
\(=\sum\limits_{p\in prime}\sum\limits_{i=1}^{\lfloor \frac{n}{p} \rfloor}\sum\limits_{j=1}^{\lfloor \frac{n}{p} \rfloor}[gcd(i,j)==1]\)
因为\(i,j\)是等效的,所以只用将\(j\)枚举到\(i\)即可,保证\(j<i\)再乘\(2\),注意只有\(i=1,j=1\)(\(i,j\)矩阵对角线上)被算两次且符合\(gcd==1\),所以再枚举完\(i\)之后要\(-1\),注意\(-1\)是在外层。
\(=\sum\limits_{p\in prime}2\sum\limits_{i=1}^{\lfloor \frac{n}{p} \rfloor}\sum\limits_{j=1}^{i}[gcd(i,j)==1]\ -1\)
我们发现里面实际就是欧拉函数
\(=\sum\limits_{p\in prime}2\sum\limits_{i=1}^{\lfloor \frac{n}{p} \rfloor}\phi(i)\ -1\)
线性筛+枚举即可
还是好好记一下线性筛计算欧拉函数的几个公式

\(Code\)

#include<cstdio>
#include<iostream>
#include<cstring>
#define maxn 10000010
#define re register
#define ll long long
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll ans;
int n,is_not_prime[maxn],prime[maxn],pcnt,phi[maxn];
void pre()
{
    is_not_prime[1]=1;
    phi[1]=1;
    for(int i=1;i<=n;++i)
    {
        if(!is_not_prime[i])
        {
            prime[++pcnt]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=pcnt;++j)
        {
            if(i*prime[j]>n) break;
            is_not_prime[i*prime[j]]=1;
            if(i % prime[j]==0)
            {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            else phi[i * prime[j]] = phi[i] * phi[prime[j]];
        }
    }
}
int main()
{
    n=read();
    pre();
    for(re int i=1;i<=pcnt;++i)
    {
        for(re int j=1;j<=n/prime[i];++j)
        {
            ans+=2*phi[j];
        }
        ans--;
    }
    //for(re int i=1;i<=n;++i) printf("%d ",phi[i]);
    printf("%lld\n",ans);
    return 0;
}

P2568 GCD

标签:code   gcd   name   register   int   mat   solution   namespace   莫比乌斯反演   

原文地址:https://www.cnblogs.com/Liuz8848/p/11469593.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!