Luogu P2257 YY的GCD

题意

\(T\) 组数据,每组数据给定 \(n,m\),求 \(\sum\limits_{p\in P}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=p]\)。(这里 \(P\) 是质数集)

\(\texttt{Data Range:}T=10^4,1\leq n,m\leq 10^7\)

题解

第一个求和符号里面的和式很平凡,直接写出来大概是这样:

\[\sum\limits_{p\in P}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=p]=\sum\limits_{p\in P}\sum\limits_{d=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\mu(d)\left\lfloor\frac{n}{dp}\right\rfloor\left\lfloor\frac{m}{dp}\right\rfloor \]

然后我们考虑将枚举 \(d\) 改成枚举 \(T=dp\),那么有

\[\sum\limits_{p\in P}\sum\limits_{d=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\mu(d)\left\lfloor\frac{n}{dp}\right\rfloor\left\lfloor\frac{m}{dp}\right\rfloor=\sum\limits_{p\in P}\sum\limits_{T=1}^{n}\mu\left(\frac{T}{p}\right)\left\lfloor\frac{n}{T}\right\rfloor\left\lfloor\frac{m}{T}\right\rfloor \]

注意到我们可以交换一下求和变量

\[\sum\limits_{p\in P}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=p]=\sum\limits_{T=1}^{n}\left\lfloor\frac{n}{T}\right\rfloor\left\lfloor\frac{m}{T}\right\rfloor\sum\limits_{p\mid T,p\in P}\mu\left(\frac{T}{p}\right) \]

注意到在筛出 \(\mu\) 之后可以考虑通过枚举来预处理出 \(\sum\limits_{p\mid T,p\in P}\mu\left(\frac{T}{p}\right)\),然后整除分块就做完了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=1e7+51;
ll test,ptot,n,m;
ll np[MAXN],prime[MAXN],mu[MAXN];
li f[MAXN],prefix[MAXN];
inline ll read()
{
    register ll num=0,neg=1;
    register char ch=getchar();
    while(!isdigit(ch)&&ch!='-')
    {
        ch=getchar();
    }
    if(ch=='-')
    {
        neg=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch-'0');
        ch=getchar();
    }
    return num*neg;
}
inline void sieve(ll limit)
{
    np[1]=mu[1]=1;
    for(register int i=2;i<=limit;i++)
    {
        if(!np[i])
        {
            prime[++ptot]=i,mu[i]=-1;
        }
        for(register int j=1;i*prime[j]<=limit;j++)
        {
            np[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            mu[i*prime[j]]=-mu[i];
        }
    }
}
inline li calc(ll n,ll m)
{
    li res=0;
    for(register int l=1,r;l<=min(n,m);l=r+1)
    {
        r=min(n/(n/l),m/(m/l));
        res+=(prefix[r]-prefix[l-1])*(n/l)*(m/l);
    }
    return res;
}
int main()
{
    test=read(),sieve(1e7+10);
    for(register int i=1;i<=ptot;i++)
    {
        for(register int j=1;prime[i]*j<=1e7;j++)
        {
            f[prime[i]*j]+=mu[j];
        }
    }
    for(register int i=1;i<=1e7;i++)
    {
        prefix[i]=prefix[i-1]+f[i];
    }
    for(register int i=0;i<test;i++)
    {
        n=read(),m=read(),printf("%lld\n",calc(n,m));
    }
}
posted @ 2020-09-17 21:27  Karry5307  阅读(132)  评论(0编辑  收藏  举报