神犇YY虐完数论后给傻×kAc出了一题html
给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对ios
kAc这种傻×必然不会了,因而向你来请教……git
多组输入spa
第一行一个整数T 表述数据组数code
接下来T行,每行两个正整数,表示N, Mhtm
T行,每行一个整数表示第i组数据的结果blog
2ip
10get
10input
100
100
30
2791
\(T \leq 10000\)
\(N, M \leq 10000000\)
简单版:【BZOJ2818】Gcd
如下式子从【BZOJ2818】Gcd最后一步开始化。
(注:式子中\(d\)默认为质数)
\[ \begin{split} ans&=\sum\limits_{d=1}^n\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\mu(i)\lfloor\frac n{id}\rfloor\lfloor\frac m{id}\rfloor\\ 设T&=id\\ ans&=\sum\limits_{d=1}^n\sum\limits_{d|T}^n\mu(\frac Td)\lfloor\frac nT\rfloor\lfloor\frac mT\rfloor\\ &=\sum\limits_{T=1}^n\sum\limits_{d|T}\mu(\frac Td)\lfloor\frac nT\rfloor\lfloor\frac mT\rfloor\\ &=\sum\limits_{T=1}^n\lfloor\frac nT\rfloor\lfloor\frac mT\rfloor\sum\limits_{d|T}\mu(\frac Td) \end{split} \]
对于后面的\(\sum\limits_{d|T}\mu(\frac Td)\),
咱们能够选择\(O(n\log n)\)的调和级数方法预处理,
也能够根据其积性在线性筛中预处理。
以后,即可以整除分块直接\(O(\sqrt n)\)计算。
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdio> #include<iomanip> #include<cstdlib> #define MAXN 0x7fffffff typedef long long LL; const int N=1e7+5; using namespace std; inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;} int mu[N],prime[N],g[N]; bool vis[N]; int main(){ mu[1]=1; for(int i=2;i<=1e7;i++){ if(!vis[i])prime[++prime[0]]=i,mu[i]=-1,g[i]=1; for(int j=1;j<=prime[0]&&1ll*i*prime[j]<=1e7;j++){ vis[i*prime[j]]=1; if(i%prime[j]==0){ g[i*prime[j]]=mu[i]; break; } mu[i*prime[j]]=-mu[i]; g[i*prime[j]]=mu[i]-g[i]; } } for(int i=2;i<=1e7;i++)g[i]+=g[i-1]; int T=Getint(); while(T--){ int n=Getint(),m=Getint(); 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+=1ll*(n/l)*(m/l)*(g[r]-g[l-1]); } cout<<ans<<'\n'; } return 0; }