[Explanations] luogu P2257 YY of GCD

Yuan Ye's gcd

First, be sure that this is the number one topic

Therefore, topic is: \ (\ sum_. 1} = {I ^ N \ sum_. 1} = {J ^ M [GCD (I, J) \ in Prime] \)

Then you can push a pleasant expression of ~

First, you can follow the routine enumeration prime and gcd

\(\sum_{p \in prime}\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)=p]\)

So we can obviously \ (I \) and \ (J \) simultaneously divided by \ (P \) , to give
\ (\ sum_ {p \ in prime} \ sum_ {i = 1} ^ {N} \ sum_ { j = 1} ^ {M} [gcd (\ frac ip, \ frac jp) = 1] \)

That is equivalent to
\ (\ sum_ {p \ in prime} \ sum_ {i = 1} ^ {\ frac Np} \ sum_ {j = 1} ^ {\ frac Mp} [gcd (i, j) = 1] \)

To here, we found that for \ ([gcd (i, j ) = 1] \) we can define the function Möbius \ (\ sum_ {d \ mid n} \ mu (d) \ = [n = 1] \) to be replaced, i.e.,

\(\sum_{p \in prime}\sum_{i=1}^{\frac Np}\sum_{j=1}^{\frac Mp}\sum_{d\mid i,d\mid j} \mu(d)\)

We can follow the routine \ (d \) in advance (here we default \ (N \ Le M \) )

\(\sum_{p \in prime}\sum_{d=1}^{\frac Np}\mu(d)\sum_{i=1}^{\frac Np}[d\mid i]\sum_{j=1}^{\frac Mp}[d\mid j]\)

Then we can find behind those two \ (\ sum \) can be divisible block out, that is,

\(\sum_{p \in prime}\sum_{d=1}^{\frac Np}\mu(d)\lfloor\frac N{dp}\rfloor\lfloor\frac M{dp}\rfloor\)

In this case, we use a little trick, the last formula \ (dp \) into \ (Q \)(Also known as Liu Chen Xue Ke Cui Jia He):

\(\sum_{Q=1}^N \sum_{p \in prime}\mu(\frac Qp)\lfloor\frac N{Q}\rfloor\lfloor\frac M{Q}\rfloor\)

For \ (\ sum_ {P \} in Prime \ MU (\ Qp of FRAC) \ lfloor \ N FRAC {Q} \ rfloor \ lfloor \ FRAC {Q M} \ rfloor \) , we may be pretreated with a linear screen, that is screening out \ (\ varphi \) enumeration after. Therefore, maintenance and after you can prefix for each inquiry \ (O (1) \) answered friends ~

\(\mathcal{Code:}\)

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 10000010
#define debug cout<<__LINE__<<" "<<__FUNCTION__<<"\n"
inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x;
}
void put(long long x){
    if(x<0) putchar('-'),x=-x;
    if(x>=10) put(x/10);
    putchar((x%10)+48);
}
int prime[N>>2],n,m,cnt;
bool ispri[N];
int mu[N],num[N];
inline void pri(){
    register int i,j;
    for(i=2;i<=N-10;i++){
        if(!ispri[i]){
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for(j=1;j<=cnt&&(i*prime[j]<=N-10);j++){
            if(i*prime[j]<=N-10) ispri[i*prime[j]]=1;
            if(i%prime[j]==0){
                break;
            }else{
                mu[i*prime[j]]=-mu[i];
            }
        }
    }
    int res;
    for(i=1;i<=cnt;i++){
        res=1;
        for(j=prime[i];j<=N-10;j+=prime[i],res++){
            num[j]+=mu[res];
        }
    }
    for(i=2;i<=N-10;i++) num[i]+=num[i-1];
}
signed main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    mu[1]=1;
    pri();
    int T=read(),l,r;
    long long ans = 0;
    while(T--){
        n=read();m=read();ans=0;
        if(n>m) swap(n,m);
        for(l=1,r;l<=n;l=r+1){
            r=min(n/(n/l),m/(m/l));
            ans+=(long long)(num[r]-num[l-1])*(n/l)*(m/l);
        }
        put(ans);putchar('\n');
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

Guess you like

Origin www.cnblogs.com/end-of-mind/p/11515298.html