【题解】Luogu P4450 双亲数

原题传送门

这题需要运用莫比乌斯反演(懵逼钨丝繁衍)

设F(t)表示满足gcd(x,y)%t=0的数对个数,f(t)表示满足gcd(x,y)=t的数对个数,实际上答案就是f(d)

这就满足莫比乌斯反演的关系式了

显然我们珂以得知F(t)=(b/t)*(d/t)

我们根据反演的第二个公式便珂以得出

$$f(d)=sum_{n|d}mu(frac{d}{n})F(d)$$

在用下整除分块就过了

#include <bits/stdc++.h>
#define N 1000005
#define ll long long
#define getchar nc
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf; 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register ll x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline int Min(register int a,register int b)
{
    return a<b?a:b;
}
int miu[N],v[N];
ll sum[N];
int main()
{
    for(register int i=1;i<=N;++i)
        miu[i]=1,v[i]=0;
    for(register int i=2;i<=N;++i)
    {
        if(v[i])
            continue;
        miu[i]=-1;
        for(register int j=i<<1;j<=N;j+=i)
        {
            v[j]=1;
            if((j/i)%i==0)
                miu[j]=0;
            else
                miu[j]*=-1;
        }
    }
    for(register int i=1;i<=N;++i)
        sum[i]=sum[i-1]+miu[i];
    int a=read(),b=read(),k=read();
    int maxround=Min(a/k,b/k);
    ll ans=0;
    for(register int l=1,r;l<=maxround;l=r+1)
    {
        r=Min((a/k)/((a/k)/l),(b/k)/((b/k)/l));
        ans+=(ll)((a/k)/l)*((b/k)/l)*(sum[r]-sum[l-1]);
    }
    write(ans);
    return 0;
 } 
原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10133964.html