https://www.luogu.org/problem/P2257
n , m ≤ 1 0 7 , T ≤ 1 0 4 n,m\leq 10^7,T\leq 10^4 n,m≤107,T≤104
先枚举素数
同时除以 k k k
我们知道莫比乌斯函数的性质 ∑ d ∣ n μ ( d ) = [ n = 1 ] \sum_{d|n}\mu(d)=[n=1] ∑d∣nμ(d)=[n=1]
把这个 n n n换成 g c d ( i , j ) gcd(i,j) gcd(i,j)
丢进原式
然后我们阔以枚举 d d d,把 d d d提出来,因为 d ∣ g c d ( i , j ) d|gcd(i,j) d∣gcd(i,j),所以 i , j i,j i,j都是 d d d的倍数,自然这范围中是 d d d倍数的有 ⌊ i 的 上 限 d ⌋ × ⌊ j 的 上 限 d ⌋ \lfloor \dfrac{i的上限}d\rfloor\times \lfloor \dfrac{j的上限}d\rfloor ⌊di的上限⌋×⌊dj的上限⌋个,即 ⌊ ⌊ n k ⌋ d ⌋ × ⌊ ⌊ m k ⌋ d ⌋ = ⌊ n k d ⌋ × ⌊ m k d ⌋ \lfloor\dfrac{\lfloor\dfrac nk\rfloor}d\rfloor\times \lfloor \dfrac{\lfloor\dfrac m k\rfloor}d\rfloor=\lfloor\dfrac n{kd}\rfloor\times \lfloor \dfrac m{kd}\rfloor ⌊d⌊kn⌋⌋×⌊d⌊km⌋⌋=⌊kdn⌋×⌊kdm⌋
于是原式=
设 T = k d T=kd T=kd,扔进去
后面那坨 k k k就是 T T T的质因子,是可以预处理的!!!
于是对于每一个质数 k k k,对于它的倍数 T T T,都加上一个 μ ( T k ) \mu(\dfrac Tk) μ(kT)
处理一下前缀和,打个整除分块就A了啦
时间复杂度: O ( n l o g n + T n ) O(nlogn+T\sqrt n) O(nlogn+Tn)
#include
#include
#include
#define N 10000000
#define LL long long
using namespace std;
LL mu[N+10];int prime[N>>3],m,f[N+10],sum[N+10],t,x,y;
bool vis[N+10];
inline LL read()
{
LL f=0,d=1;char c;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline LL solve(int a,int b)
{
LL res=0;
for(register int l=1,r=0;l<=a;l=r+1)
{
r=min(a/(a/l),b/(b/l));
res+=(LL)(sum[r]-sum[l-1])*(LL)(a/l)*(b/l);
}
return res;
}
signed main()
{
mu[1]=1;
for(register int i=2;i<=N;i++)
{
if(vis[i]==0) {prime[++m]=i;mu[i]=-1;}
for(register int j=1;j<=m&&prime[j]*i<=N;j++)
{
vis[prime[j]*i]=true;
if(i%prime[j]==0) break;
mu[prime[j]*i]=-mu[i];
}
}
for(register int i=1;i<=m;i++)
for(register int j=1;prime[i]*j<=N;j++)
f[j*prime[i]]+=mu[j];
for(register int i=1;i<=N;i++) sum[i]=sum[i-1]+f[i];
for(t=read();t--;)
{
x=read();y=read();
if(x>y) x^=y,y=x^y,x^=y;
printf("%lld\n",solve(x,y));
}
}