问题描述

BZOJ2820

LG2257


题解

\(\sum\limits_{i=1}^{n}{\sum\limits_{j=1}^{m}{[gcd(i,j)==p]}}\) ,其中 \(p\)为质数,\(n<m\)

考虑不要求 \(gcd(i,j)\) 为质数时的做法:

可以转化为

\[\sum\limits_{g=1}^{n}{g \times \sum\limits_{i=1}^{\lfloor \frac{n}{g} \rfloor}{\sum\limits_{j=1}^{\lfloor \frac{m}{g} \rfloor}{[gcd(i,j)==1]}}}\]

转化为枚举倍数,得

\[\sum\limits_{g=1}^{n}{g \times \sum\limits_{i=1}^{\lfloor \frac{n}{g} \rfloor}{\sum\limits_{j=1}^{\lfloor \frac{m}{g} \rfloor}{\sum\limits_{x|gcd(i,j)}{\mu(x)}}}}\]


\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std;

const int maxn=10000000;

int p[maxn+7],pr[maxn+7],miu[maxn+7];
int h[maxn+7],T,tot;

long long s[maxn+7];

void preprocess(void){
    miu[1]=1;
    for(int i=2;i<=maxn;i++){
        if(!p[i]) p[i]=i,pr[++tot]=i,miu[i]=-1;
        for(int j=1;j<=tot;j++){
            if((long long)i*pr[j]>maxn||pr[j]>p[i]) break;
            p[i*pr[j]]=pr[j];
            if(i%pr[j]) miu[i*pr[j]]=-miu[i];
            else miu[i*pr[j]]=0;
        }
    }
    for(int i=1;i<=tot;i++){
        for(int j=1;(long long)pr[i]*j<=maxn;j++){
            h[pr[i]*j]+=miu[j];
        }
    }
    for(int i=1;i<=maxn;i++) s[i]=s[i-1]+(long long)h[i];
}

void Init(void){
    scanf("%d",&T);
}

long long calc(int x,int y){
    if(x>y) swap(x,y);
    long long res(0);
    for( int l=1,r;l<=x;l=r+1){
        r=min(x/(x/l),y/(y/l));
        res+=(long long)(s[r]-s[l-1])*(long long)(x/l)*(y/l);
    }
    return res;
}

void Work(void){
    preprocess();
    while(T--){
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%lld\n",calc(x,y));
    }
}

signed main(){
    Init();
    Work();
}
12-29 17:45