## 约数个数求和+线性筛约数——bzoj3994

bool vis[maxn];
int mm,mu[maxn],prime[maxn],num[maxn],sum[maxn],d[maxn],sum1[maxn];
void init(){
mu[1]=1;num[1]=1;
for(int i=2;i<maxn;i++){
if(!vis[i]){
prime[++mm]=i;
mu[i]=-1;
num[i]=2;
d[i]=1;
}
for(int j=1;j<=mm;j++){
if(prime[j]*i>=maxn)break;
vis[i*prime[j]]=1;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
d[i*prime[j]]=d[i]+1;
num[i*prime[j]]=num[i]/(d[i]+1)*(d[i*prime[j]]+1);
break;
}
else {
mu[i*prime[j]]=-mu[i];
d[i*prime[j]]=1;
num[i*prime[j]]=num[i]*2;
}
}
}
for(int i=1;i<maxn;i++)sum[i]=sum[i-1]+mu[i];
for(int i=1;i<maxn;i++)sum1[i]=sum1[i-1]+num[i];
}
View Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 500005
#define ll long long

bool vis[maxn];
int mm,mu[maxn],prime[maxn],num[maxn],sum[maxn],d[maxn],sum1[maxn];
void init(){
mu[1]=1;num[1]=1;
for(int i=2;i<maxn;i++){
if(!vis[i]){
prime[++mm]=i;
mu[i]=-1;
num[i]=2;
d[i]=1;
}
for(int j=1;j<=mm;j++){
if(prime[j]*i>=maxn)break;
vis[i*prime[j]]=1;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
d[i*prime[j]]=d[i]+1;
num[i*prime[j]]=num[i]/(d[i]+1)*(d[i*prime[j]]+1);
break;
}
else {
mu[i*prime[j]]=-mu[i];
d[i*prime[j]]=1;
num[i*prime[j]]=num[i]*2;
}
}
}
for(int i=1;i<maxn;i++)sum[i]=sum[i-1]+mu[i];
for(int i=1;i<maxn;i++)sum1[i]=sum1[i-1]+num[i];
}
ll n,m;

inline ll calc(ll n,ll m){return (ll)sum1[n]*sum1[m];}

int main(){
init();
int t;cin>>t;
while(t--){
cin>>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+=(sum[r]-sum[l-1])*calc(n/l,m/l);
}
cout<<ans<<'\n';
}
}

posted on 2019-07-08 16:11  zsben  阅读(198)  评论(0编辑  收藏  举报