先链popoqqq大爷的题解
然后看本蒟蒻口胡(雾),毕竟50题了qwq
嗯首先莫比乌斯反演在popoqqq大爷的题解里面已经很详细了。。
然后我就贴代码放筛法了……莫比乌斯反演一下,O(n)预处理,O(Tk)分块查询。。k=两个输入的数的约数交集的大小 - -
然后就A了啊 - - (其实我还不是很懂啊qwq所以太弱也讲不清什么qwq
#include "stdio.h" #include "math.h" #include "stdlib.h" #include "algorithm" #include "iostream" #define rep(f,a,b) for(f=a;f<=b;f++) #define run(f,to) for(f=1;f<=to;f++) #define re(f) for(f=2;f<=fto;f++) #define fto 10000000 #define N 10000005 #define M 2000005 using namespace std; typedef long long ll; inline int read(){ int v=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch<='9'&&ch>='0') { v=v*10+ch-'0'; ch=getchar();} return v; } ll g[N],sg[N]; int pri[M],len,ti[N],mnl[N]; bool flag[N]; void build(){ // 筛法:线性筛g函数,pri[x]代表x的只包含其最小质因子的最大的约数,ti代表其次数
<pre name="code" class="cpp"> //然后显然pri<=i,所以筛法就很清晰了啊……<del>只要理解了线性筛的,这个应该不难吧(除了我这种大蒟蒻TAT</del>int i,j,k; re(i){if(!flag[i]) g[i]=ti[i]=1,mnl[i]=i,pri[++len]=i;for (j=1;pri[j]*i<=fto;j++){k=i*pri[j]; flag[k]=true; if (i%pri[j]==0){ ti[k]=ti[i]+1; mnl[k]=mnl[i]*pri[j]; int tmp=i/mnl[i];g[k]=tmp==1?1: ti[tmp]==ti[k]?-g[tmp]:0; break;}ti[k]=1; mnl[k]=pri[j]; g[k]=ti[i]==1?-g[i]:0;}}re(i) sg[i]=sg[i-1]+g[i];}void work(){int q=read(),a,b,i,j,last,c;run(j,q){a=read(),b=read(); ll ans=0;for (i=1,c=min(a,b);i<=c;i=last+1){last=min(a/(a/i),b/(b/i));ans+=(ll)(a/i)*(b/i)*(sg[last]-sg[i-1]);}printf("%lld\n",ans);}}int main(){build(); work();return 0;}