首先这个东西我们必须要把它转化成式子不然没法推。
考虑利用莫比乌斯函数转化一下,我们要求的就是:
∑ i = 1 n ∑ j = 1 m l c m ( i , j ) ∣ μ ( g c d ( i , j ) ) ∣ \sum_{i=1}^n\sum_{j=1}^mlcm(i,j)|\mu(gcd(i,j))| i=1∑nj=1∑mlcm(i,j)∣μ(gcd(i,j))∣
注意上面 μ \mu μ外面套的是绝对值符号。
我必须承认这个式子看着很鬼畜,但是只要不怕转化,就能化出来: A n s = ∑ i = 1 n ∑ j = 1 m i j g c d ( i , j ) ∣ μ ( g c d ( i , j ) ) ∣ = ∑ d = 1 min ( n , m ) ∑ i = 1 n ∑ j = 1 m i j d ∣ μ ( d ) ∣ [ g c d ( i , j ) = d ] = ∑ d = 1 min ( n , m ) d ∣ μ ( d ) ∣ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j [ g c d ( i , j ) = 1 ] \begin{aligned} Ans=&\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{gcd(i,j)}|\mu(gcd(i,j))|\\ =&\sum_{d=1}^{\min(n,m)}\sum_{i=1}^n\sum_{j=1}^m\frac{ij}d|\mu(d)|[gcd(i,j)=d]\\ =&\sum_{d=1}^{\min(n,m)}d|\mu(d)|\sum_{i=1}^{\lfloor\frac{n}d\rfloor}\sum_{j=1}^{\lfloor\frac{m}d\rfloor}ij[gcd(i,j)=1] \end{aligned} Ans===i=1∑nj=1∑mgcd(i,j)ij∣μ(gcd(i,j))∣d=1∑min(n,m)i=1∑nj=1∑mdij∣μ(d)∣[gcd(i,j)=d]d=1∑min(n,m)d∣μ(d)∣i=1∑⌊dn⌋j=1∑⌊dm⌋ij[gcd(i,j)=1]
当出现形如 [ n = 1 ] [n=1] [n=1]的求和式子的时候,我们知道,可以开始反演了:
A n s = ∑ d = 1 min ( n , m ) d ∣ μ ( d ) ∣ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j ∑ t ∣ g c d ( i , j ) μ ( t ) \begin{aligned} Ans=&\sum_{d=1}^{\min(n,m)}d|\mu(d)|\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}ij\sum_{t\mid gcd(i,j)}\mu(t) \end{aligned} Ans=d=1∑min(n,m)d∣μ(d)∣i=1∑⌊dn⌋j=1∑⌊dm⌋ijt∣gcd(i,j)∑μ(t)
接下来用 S ( n ) S(n) S(n)来表示 ∑ i = 1 n i \sum_{i=1}^ni ∑i=1ni,显然上面的 i j ij ij用结合律拆开后可以简化。得到: A n s = ∑ d = 1 min ( n , m ) d ∣ μ ( d ) ∣   S ( ⌊ n d ⌋ ) S ( ⌊ m d ⌋ ) ∑ t ∣ g c d ( i , j ) , i ≤ ⌊ n d ⌋ , j ≤ ⌊ m d ⌋ μ ( t ) = ∑ d = 1 min ( n , m ) d ∣ μ ( d ) ∣ ∑ t = 1 min ( n , m ) d t 2 μ ( t ) S ( ⌊ n d t ⌋ ) S ( ⌊ m d t ⌋ ) \begin{aligned} Ans=&\sum_{d=1}^{\min(n,m)}d|\mu(d)|\,S(\lfloor\frac{n}d\rfloor)S(\lfloor\frac{m}d\rfloor)\sum_{t\mid gcd(i,j),i\leq \lfloor\frac{n}d\rfloor,j\leq \lfloor\frac{m}{d}\rfloor}\mu(t)\\ =&\sum_{d=1}^{\min(n,m)}d|\mu(d)|\sum_{t=1}^{\frac{\min(n,m)}{d}}t^2\mu(t)S(\lfloor\frac{n}{dt}\rfloor)S(\lfloor\frac{m}{dt}\rfloor) \end{aligned} Ans==d=1∑min(n,m)d∣μ(d)∣S(⌊dn⌋)S(⌊dm⌋)t∣gcd(i,j),i≤⌊dn⌋,j≤⌊dm⌋∑μ(t)d=1∑min(n,m)d∣μ(d)∣t=1∑dmin(n,m)t2μ(t)S(⌊dtn⌋)S(⌊dtm⌋)
这个 d t dt dt很麻烦,考虑直接枚举: A n s = ∑ T = 1 min ( n , m ) S ( ⌊ n T ⌋ ) S ( ⌊ m T ⌋ )   T ∑ d ∣ T d μ ( d ) ∣ μ ( T d ) ∣ \begin{aligned} Ans=&\sum_{T=1}^{\min(n,m)}S(\lfloor\frac{n}T\rfloor)S(\lfloor\frac{m}T\rfloor)\,T\sum_{d\mid T}d\mu(d)|\mu(\frac{T}d)| \end{aligned} Ans=T=1∑min(n,m)S(⌊Tn⌋)S(⌊Tm⌋)Td∣T∑dμ(d)∣μ(dT)∣
前面那一坨已经可以考虑整除分块了,但是我们要找到一个高效的方法维护这个东西的前缀和: g ( T ) = T ∑ d ∣ T d μ ( d ) ∣ μ ( T d ) ∣ g(T)=T\sum_{d\mid T}d\mu(d)|\mu(\frac{T}d)| g(T)=T∑d∣Tdμ(d)∣μ(dT)∣
其实就是这个东西 g = I d ⋅ ( ( I d ⋅ μ ) ∗ ∣ μ ∣ ) g=Id\cdot ((Id\cdot \mu)*|\mu|) g=Id⋅((Id⋅μ)∗∣μ∣)
我们知道积性函数的乘积和 D i r i c h l e t Dirichlet Dirichlet卷积结果仍然是积性函数,换句话说, g g g是积性函数,可以在线性筛的时候一起处理。
那么首先显然有:
g ( 1 ) = 1 g(1)=1 g(1)=1
∀ p ∈ P , g ( p ) = p ( 1 − p ) \forall p\in \mathbb P,g(p)=p(1-p) ∀p∈P,g(p)=p(1−p),这个可以通过直接展开得到
∀ p ∈ P , n ∈ N ∗ , g c d ( n , p ) = 1 , g ( p n ) = g ( p ) g ( n ) \forall p\in \mathbb P,n\in \mathbb N_*,gcd(n,p)=1,g(pn)=g(p)g(n) ∀p∈P,n∈N∗,gcd(n,p)=1,g(pn)=g(p)g(n),这个由积性函数性质得到。
那么现在需要考虑的就是 p ∈ P , n ∈ N ∗ , g c d ( n , p ) = p p\in \mathbb P,n\in \mathbb N_*,gcd(n,p)=p p∈P,n∈N∗,gcd(n,p)=p,怎么求 g ( n p ) g(np) g(np)。
首先,将 n n n分解: n = n ′ × p s n=n'\times p^s n=n′×ps
如果 s ≥ 2 s\geq 2 s≥2,那么 n p np np中至少含有三个 p p p这个因子,那么这一项 μ ( d ) ∣ μ ( T d ) ∣ \mu(d)|\mu(\frac{T}d)| μ(d)∣μ(dT)∣就恒为 0 0 0(根据抽屉原理),此时 g ( n p ) = 0 g(np)=0 g(np)=0
不然, s = 1 s=1 s=1,我们可以得到: g ( n p ) = g ( n p ) g ( p 2 ) g(np)=g(\frac{n}p)g(p^2) g(np)=g(pn)g(p2)。
考虑怎么求 g ( p 2 ) g(p^2) g(p2)。
其实我们可以暴力展开:
g ( p 2 ) = p 2 ⋅ ( 1 ⋅ μ ( 1 ) ⋅ ∣ μ ( p 2 ) ∣ + p ⋅ μ ( p ) ∣ μ ( p ) ∣ + p 2 ⋅ μ ( p 2 ) ∣ μ ( 1 ) ∣ ) = − p 3 g(p^2)=p^2\cdot\big(1\cdot\mu(1)\cdot|\mu(p^2)|+p\cdot\mu(p)|\mu(p)|+p^2\cdot\mu(p^2)|\mu(1)|\big)=-p^3 g(p2)=p2⋅(1⋅μ(1)⋅∣μ(p2)∣+p⋅μ(p)∣μ(p)∣+p2⋅μ(p2)∣μ(1)∣)=−p3
这道题就做完了。
代码:
#include
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc putchar
#define cs const
namespace IO{
namespace IOONLY{
cs int Rlen=1<<18|1;
char buf[Rlen],*p1,*p2;
}
inline char get_char(){
using namespace IOONLY;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
cs int P=4000006;
int prime[P],pcnt;
int g[P];
bool mark[P];
inline void linear_sieves(int len=P-6){
g[1]=1;
for(int re i=2;i<=len;++i){
if(!mark[i])prime[++pcnt]=i,g[i]=i*(1-i);
for(int re j=1;i*prime[j]<=len;++j){
mark[i*prime[j]]=true;
if(i%prime[j]==0){
if(i/prime[j]%prime[j])g[i*prime[j]]=-prime[j]*prime[j]*prime[j]*g[i/prime[j]];
else g[i*prime[j]]=0;
break;
}
g[i*prime[j]]=g[i]*g[prime[j]];
}
}
for(int re i=2;i<=len;++i)g[i]+=g[i-1];
}
inline int S(cs int n){
return n*(n+1ll)/2;}
inline int solve(int n,int m){
if(n>m)swap(n,m);
unsigned int ans=0;
for(int re i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
ans+=(g[j]-g[i-1])*S(n/i)*S(m/i);
}
return ans&((1<<30)-1);
}
signed main(){
linear_sieves();
for(int re T=getint();T--;cout<<solve(getint(),getint())<<'\n');
return 0;
}