Luogu P2257 YY的GCD 莫比乌斯反演

第一道莫比乌斯反演。。。$qwq$


 

设$f(d)=\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d]$

$F(n)=\sum_{n|d}f(d)=\lfloor \frac{N}{n} \rfloor \lfloor \frac{M}{n} \rfloor$

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

$ans=\sum_{p\in pri}f(p)$

$=\sum_{p\in pri}\sum_{p|d}\mu(\frac{d}{p})F(d)$

$=\sum_{d=1}^{min(N,M)}\sum_{p\in pri且p|d}\space\mu(\frac{d}{p})F(d)$

$=\sum_{d=1}^{min(N,M)}F(d)\sum_{p\in pri且p|d}\space\mu(\frac{d}{p})$

$=\sum_{d=1}^{min(N,M)}\lfloor \frac{N}{d} \rfloor \lfloor \frac{M}{d} \rfloor \sum_{p\in pri且p|d}\space\mu(\frac{d}{p})$

对于$\lfloor \frac{N}{d} \rfloor \lfloor \frac{M}{d} \rfloor$用整除分块,对于$a(d)=\sum_{p\in pri且p|d}\space\mu(\frac{d}{p})$用一个类似埃筛的思路把$a(d)$筛出来然后做一个前缀和。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define R register int
using namespace std;
namespace Fread {
    static char B[1<<15],*S=B,*D=B;
    #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
}using Fread::g;
int t,n,m,cnt,pri[1000000],a[10000001],mu[10000001];
bool v[10000001]; long long sum[10000001];
inline void MU(int n) { mu[1]=1;
    for(R i=2;i<=n;++i) {
        if(!v[i]) pri[++cnt]=i,mu[i]=-1;
        for(R j=1;j<=cnt&&i*pri[j]<=n;++j) {
            v[i*pri[j]]=true;
            if(i%pri[j]==0) break;
            else mu[i*pri[j]]=-mu[i];
        }
    } for(R j=1;j<=cnt;++j) for(R i=1;i*pri[j]<=n;++i) a[i*pri[j]]+=mu[i];
    for(R i=1;i<=n;++i) sum[i]=sum[i-1]+(ll)a[i];
}
signed main() {
#ifdef JACK
    freopen("NOIPAK++.in","r",stdin);
#endif
    MU(10000000); t=g(); while(t--) { register long long ans=0;
        n=g(),m=g(); n>m?(void)(swap(n,m)):(void)0;
        for(R l=1,r;l<=n;l=r+1) {
            r=min(n/(n/l),m/(m/l));
            ans+=(ll)(n/l)*(m/l)*(sum[r]-sum[l-1]);
        }printf("%lld\n",ans);
    }
} 

2019.06.09

posted @ 2019-06-09 10:12  LuitaryiJack  阅读(147)  评论(0编辑  收藏  举报