Luogu2257 YY的GCD

https://www.luogu.com.cn/problem/P2257

莫比乌斯反演

\[令N\le M\\ \sum_{i=1}^N \sum_{j=1}^M [gcd(i,j)\in prime]\\ =\sum_{k \in prime} \sum_{i=1}^{\lfloor \frac{N}{k} \rfloor} \sum_{j=1}^{\lfloor \frac{M}{k} \rfloor} [\gcd(i,j)=1]\\ =\sum_{k \in prime} \sum_{i=1}^{\lfloor \frac{N}{k} \rfloor} \sum_{j=1}^{\lfloor \frac{M}{k} \rfloor} \sum_{d|i,d|j}\mu(d)\\ =\sum_{k \in prime} \sum_{d=1}^N \mu(d) \sum_{i=1}^{\lfloor \frac{N}{kd} \rfloor} \sum_{j=1}^{\lfloor \frac{M}{kd} \rfloor} 1\\ =\sum_{T=1}^N \sum_{i=1}^{\lfloor \frac{N}{T} \rfloor} \sum_{j=1}^{\lfloor \frac{M}{T} \rfloor}\sum_{k \in prime,k|T} \mu(\frac{T}{k})\\ 前缀和预处理\sum_{k \in prime,k|T} \mu(\frac{T}{k}),剩下的数论分块就好了 \]

\(C++ Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define N 10000000
using namespace std;
int T,n,m,l,r;
ll ans;
bool pri[N+5];
int cnt,prime[N+5],mu[N+5],kz[N+5];
void Pre()
{
    mu[1]=1;
    for (int i=2;i<=N;i++)
    {
        if (!pri[i])
        {
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for (int j=1;j<=cnt;j++)
        {
            ll g=(ll)i*prime[j];
            if (g>N)
                break;
            pri[g]=true;
            if (i%prime[j]==0)
            {
                mu[g]=0;
                break;
            }
            mu[g]=-mu[i];
        }
    }
    for (int i=1;i<=cnt;i++)
        for (int j=prime[i];j<=N;j+=prime[i])
            kz[j]+=mu[j/prime[i]];
    for (int i=1;i<=N;i++)
        kz[i]+=kz[i-1];
}
int main()
{
    Pre();
    scanf("%d",&T);
    while (T --> 0)
    {
        scanf("%d%d",&n,&m);
        if (n>m)
            swap(n,m);
        ans=0;
        for (l=1;l<=n;l=r+1)
        {
            r=min(n/(n/l),m/(m/l));
            ans=ans+(ll)(n/l)*(ll)(m/l)*(ll)(kz[r]-kz[l-1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2020-07-29 15:36  GK0328  阅读(60)  评论(0编辑  收藏  举报