[SDOI2015]约数个数和

https://blog.csdn.net/ab_ever/article/details/76737617

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50000+5;
int n,m,t;
ll g[N];
int u[N],su[N];
bool vis[N];
int pri[N],tot;
void sieve(){
    u[1]=1;
    for(int i=2;i<=N-3;i++){
        if(!vis[i]){
            pri[++tot]=i;
            u[i]=-1;
        }
        for(int j=1;j<=tot;j++){
            if(pri[j]*i>N-3) break;
            vis[pri[j]*i]=1;
            if(i%pri[j]==0){
                u[pri[j]*i]=0;
                break;
            }
            else u[pri[j]*i]=-u[i];
        }
    }
}
ll p[N];//wrk for g
void pre(){
    for(int i=1;i<=N-3;i++)su[i]=su[i-1]+u[i];
    for(int i=1;i<=N-3;i++){
        for(int j=i;j<=N-3;j+=i){
            p[j]++;
        }
    }
    for(int i=1;i<=N-3;i++) g[i]=g[i-1]+p[i];
}
int main(){
    sieve();
    pre();
    cin>>t;
    while(t--){
        scanf("%d%d",&n,&m);
        int ptr=1;
        ll ans=0;
        for(;ptr*ptr<=max(n,m)&&ptr<=min(n,m);ptr++){
            ans+=u[ptr]*g[n/ptr]*g[m/ptr];
        }
        if(ptr>min(n,m)) {
            printf("%lld\n",ans);
            continue;
        }
        if(n>m) swap(n,m);
        int rn=n/ptr,rm=m/ptr;
        int pn,pm;
        while(1){
            pn=n/rn,pm=m/rm;
            int tmp=min(pn,pm);
            ans+=(su[tmp]-su[ptr-1])*g[rn]*g[rm];
            if(tmp==n) break;
            ptr=tmp+1;
            rn=n/ptr,rm=m/ptr;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

/*
   Author: *Miracle*
   Date: 2018/10/4 22:08:25
*/

 

posted @ 2018-10-04 23:05  *Miracle*  阅读(172)  评论(0编辑  收藏  举报