@xzyxzy
2018-08-15T08:40:45.000000Z
字数 2838
阅读 1677
题解
首先感谢yyb的题解让我大概懂了做法
然后感谢syc的讲解让我明白的关键要点
反演的题,从yyb那里看下大概流程,然后这里讲两个地方
一个数唯一分解为,则
inline void Sieve(){ispri[1]=1;p[1]=1;d[1]=1;for(RG int i=2;i<=MAXN;i++){if(!ispri[i]){pri[++tot]=i;p[i]=1;d[i]=2;}for(RG int j=1;j<=tot&&i*pri[j]<=MAXN;j++){ispri[i*pri[j]]=1;if(i%pri[j]==0){d[i*pri[j]]=d[i]/(p[i]+1)*(p[i]+2);//d[i]表示i的因数个数p[i*pri[j]]=p[i]+1;//p[i]表示i唯一分解后最小质因子的次数break;}d[i*pri[j]]=d[i]*d[pri[j]];//实际上就是d[i]*2p[i*pri[j]]=1;}}}
这样子预处理,处理询问,总复杂度
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#define RG register#define ll long longusing namespace std;inline int read(){RG char ch=getchar();RG int h=0;while(ch>'9'||ch<'0')ch=getchar();while(ch>='0'&&ch<='9'){h=h*10+ch-'0';ch=getchar();}return h;}const int MAXN=50000;int mu[MAXN+1],pri[MAXN>>1],tot;int p[MAXN+1],d[MAXN+1],s[MAXN+1],sd[MAXN+1];bool ispri[MAXN+1];inline void Mobius(){mu[1]=1;ispri[1]=1;p[1]=1;d[1]=1;for(RG int i=2;i<=MAXN;i++){if(!ispri[i]){pri[++tot]=i;p[i]=1;mu[i]=-1;d[i]=2;}for(RG int j=1;j<=tot&&i*pri[j]<=MAXN;j++){ispri[i*pri[j]]=1;if(i%pri[j]==0){//mu[i*pri[j]]=0;//卡常d[i*pri[j]]=d[i]/(p[i]+1)*(p[i]+2);//d[i]表示i的因数个数p[i*pri[j]]=p[i]+1;//p[i]表示i唯一分解后最小质因子的次数break;}mu[i*pri[j]]=-mu[i];d[i*pri[j]]=d[i]*d[pri[j]];//实际上就是d[i]*2p[i*pri[j]]=1;}}for(RG int i=1;i<=MAXN;i++)s[i]=s[i-1]+mu[i];for(RG int i=1;i<=MAXN;i++)sd[i]=sd[i-1]+d[i];}int main(){RG int T=read();Mobius();while(T--){RG int N=read(),M=read();if(N>M)swap(N,M);RG int l=1,r;RG ll ans=0;while(l<=N){r=min(N/(N/l),M/(M/l));ans+=1LL*(s[r]-s[l-1])*sd[N/l]*sd[M/l];l=r+1;}printf("%lld\n",ans);}return 0;}