P2257 YY的GCD(莫比乌斯反演)

题目链接

题意:

给定 N , M N, M N,M,求 1 ≤ x ≤ N , 1 ≤ y ≤ M 1 \leq x \leq N,1 \leq y \leq M 1xN1yM gcd ⁡ ( x , y ) \gcd(x, y) gcd(x,y)为质数的 ( x , y ) (x, y) (x,y) 有多少对。
T T T组样例, T = 1 0 4 , N , M ≤ 1 0 7 T = 10^{4} ,N,M\leq10^{7} T=104,N,M107

推导:

根据题意写出式子,

∑ i = 1 N ∑ j = 1 M [ g c d ( i , j ) 为 质 数 ] \sum_{i=1}^{N}\sum_{j=1}^{M}[gcd(i,j)为质数] i=1Nj=1M[gcd(i,j)]

提出 g c d gcd gcd, 变成

∑ g = 1 m i n ( N , M ) ∑ i = 1 N ∑ j = 1 M [ g c d ( i , j ) = g ] [ g 为 质 数 ] \sum_{g=1}^{min(N,M)}\sum_{i=1}^{N}\sum_{j=1}^{M}[gcd(i,j)=g][g为质数] g=1min(N,M)i=1Nj=1M[gcd(i,j)=g][g]

不妨让 N < M NN<M

就变成 ∑ g = 1 N [ g 为 质 数 ] ∑ i = 1 N ∑ j = 1 M [ g c d ( i , j ) = g ] \sum_{g=1}^{N}[g为质数]\sum_{i=1}^{N}\sum_{j=1}^{M}[gcd(i,j)=g] g=1N[g]i=1Nj=1M[gcd(i,j)=g]了,写起来舒服点。

f ( g ) = ∑ i = 1 N ∑ j = 1 M [ g c d ( i , j ) = g ] f(g)=\sum_{i=1}^{N}\sum_{j=1}^{M}[gcd(i,j)=g] f(g)=i=1Nj=1M[gcd(i,j)=g]

F ( g ) = ∑ g ∣ d f ( d ) = ∑ i = 1 N ∑ j = 1 M [ g ∣ g c d ( i , j ) ] = ⌊ N g ⌋ ⌊ M g ⌋ F(g)=\sum_{g|d}f(d)=\sum_{i=1}^{N}\sum_{j=1}^{M}[g|gcd(i,j)]=\lfloor \frac{N}{g}\rfloor \lfloor\frac{M}{g} \rfloor F(g)=gdf(d)=i=1Nj=1M[ggcd(i,j)]=gNgM

根据莫比乌斯反演公式有 f ( g ) = ∑ g ∣ d μ ( d g ) F ( d ) f(g)=\sum_{g|d}\mu(\frac{d}{g})F(d) f(g)=gdμ(gd)F(d)

代回原式子得,

∑ g = 1 N [ g 为 质 数 ] f ( g ) = ∑ g = 1 N [ g 为 质 数 ] ∑ g ∣ d μ ( d g ) ⌊ N d ⌋ ⌊ M d ⌋ \sum_{g=1}^{N}[g为质数]f(g)=\sum_{g=1}^{N}[g为质数]\sum_{g|d}\mu(\frac{d}{g})\lfloor \frac{N}{d}\rfloor \lfloor\frac{M}{d} \rfloor g=1N[g]f(g)=g=1N[g]gdμ(gd)dNdM

                                       = ∑ d = 1 N ⌊ N d ⌋ ⌊ M d ⌋ ∑ g ∣ d μ ( d g ) [ g 为 质 数 ] =\sum_{d=1}^{N}\lfloor \frac{N}{d}\rfloor \lfloor\frac{M}{d} \rfloor\sum_{g|d}\mu(\frac{d}{g})[g为质数] =d=1NdNdMgdμ(gd)[g]

                                       = ∑ d = 1 N ⌊ N d ⌋ ⌊ M d ⌋ S ( d ) =\sum_{d=1}^{N}\lfloor \frac{N}{d}\rfloor \lfloor\frac{M}{d} \rfloor S(d) =d=1NdNdMS(d)

其中我们令 S ( d ) = ∑ g ∣ d μ ( d g ) [ g 为 质 数 ] S(d)=\sum_{g|d}\mu(\frac{d}{g})[g为质数] S(d)=gdμ(gd)[g],我们只要预处理出 S ( d ) S(d) S(d), 再处理出 S ( d ) S(d) S(d)的前缀和,就可以用数论分块求答案了。

那么预处理 S ( d ) S(d) S(d),我们可以对于每个数分解质因子计算贡献,也可以对于每个质数,把贡献加到它的所有倍数中,两种做法都可以 o ( n l o g n ) o(nlogn) o(nlogn)

代码:

#include
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
typedef pair<int,int> P;
const int MAXN=10000000;

int prime[MAXN+10],notPrime[MAXN+10],mu[MAXN+10],tot;
void initMu(int n)
{
    notPrime[1]=mu[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!notPrime[i])prime[tot++]=i,mu[i]=-1;
        for(int j=0;j<tot&&i*prime[j]<=n;j++)
        {
            notPrime[i*prime[j]]=1;
            if(i%prime[j])mu[i*prime[j]]=-mu[i];
            else {mu[i*prime[j]]=0;break;}
        }
    }
}

int f[MAXN+10];
int main()
{
    initMu(MAXN);
    for(int i=1;i<=MAXN;i++)if(!notPrime[i])
    {
        for(int j=i;j<=MAXN;j+=i)
        {
            f[j]+=mu[j/i];
        }
    }
    for(int i=1;i<=MAXN;i++)f[i]+=f[i-1];
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        if(n>m)swap(n,m);
        ll ans=0;
        for(int l=1,r;l<=n;l=r+1)
        {
            r=min(n/(n/l),m/(m/l));
            ans=ans+1ll*(n/l)*(m/l)*(f[r]-f[l-1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(莫比乌斯反演)