题目链接:https://www.luogu.com.cn/problem/P1829
题目大意:给定一组 n , m n,m n,m ,求 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) m o d 20101009 \sum\limits_{i=1}^n\sum\limits_{j=1}^mlcm(i,j) \space mod\space 20101009 i=1∑nj=1∑mlcm(i,j) mod 20101009 的值。
题解:直接上推导式子的过程。根据数论函数求和的题目的一些套路,我们可以尝试把原式转化为可以应用数论分块的求和式,从而降低求和的时间复杂度。不妨先设 n ≤ m n\le m n≤m 。
原式: ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) \sum\limits_{i=1}^n\sum\limits_{j=1}^mlcm(i,j) i=1∑nj=1∑mlcm(i,j)
= ∑ i = 1 n ∑ j = 1 m i j g c d ( i , j ) =\sum\limits_{i=1}^n\sum\limits_{j=1}^m\frac{ij}{gcd(i,j)} =i=1∑nj=1∑mgcd(i,j)ij
= ∑ i = 1 n ∑ j = 1 m ∑ d = 1 n i j d [ g c d ( i , j ) = d ] =\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{d=1}^n\frac{ij}{d}[gcd(i,j)=d] =i=1∑nj=1∑md=1∑ndij[gcd(i,j)=d]
= ∑ d = 1 n ∑ i = 1 n ∑ j = 1 m i j d [ g c d ( i , j ) = d ] =\sum\limits_{d=1}^n\sum\limits_{i=1}^n\sum\limits_{j=1}^m\frac{ij}{d}[gcd(i,j)=d] =d=1∑ni=1∑nj=1∑mdij[gcd(i,j)=d]
= ∑ d = 1 n d 2 ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j d [ g c d ( i , j ) = 1 ] =\sum\limits_{d=1}^nd^2\sum\limits_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{d}\rfloor}\frac{ij}{d}[gcd(i,j)=1] =d=1∑nd2i=1∑⌊dn⌋j=1∑⌊dm⌋dij[gcd(i,j)=1]
= ∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j ε ( g c d ( i , j ) ) =\sum\limits_{d=1}^nd\sum\limits_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{d}\rfloor}ij\varepsilon(gcd(i,j)) =d=1∑ndi=1∑⌊dn⌋j=1∑⌊dm⌋ijε(gcd(i,j))
= ∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j ∑ t ∣ i , t ∣ j μ ( t ) =\sum\limits_{d=1}^nd\sum\limits_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{d}\rfloor}ij\sum\limits_{t\mid i,t\mid j}\mu(t) =d=1∑ndi=1∑⌊dn⌋j=1∑⌊dm⌋ijt∣i,t∣j∑μ(t)
= ∑ d = 1 n d ∑ t = 1 ⌊ n d ⌋ μ ( t ) t 2 ∑ i = 1 ⌊ n d t ⌋ ∑ j = 1 ⌊ m d t ⌋ i j =\sum\limits_{d=1}^nd\sum\limits_{t=1}^{\lfloor \frac{n}{d}\rfloor}\mu(t)t^2\sum\limits_{i=1}^{\lfloor \frac{n}{dt}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{dt}\rfloor}ij =d=1∑ndt=1∑⌊dn⌋μ(t)t2i=1∑⌊dtn⌋j=1∑⌊dtm⌋ij
设 f ( x , y ) = ∑ t = 1 x μ ( t ) t 2 ∑ i = 1 ⌊ x t ⌋ ∑ j = 1 ⌊ y t ⌋ i j ( x ≤ y ) f(x,y)=\sum\limits_{t=1}^{x}\mu(t)t^2\sum\limits_{i=1}^{\lfloor \frac{x}{t}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{y}{t}\rfloor}ij\space(x\le y) f(x,y)=t=1∑xμ(t)t2i=1∑⌊tx⌋j=1∑⌊ty⌋ij (x≤y)
显然,对于式子的后半部分 ∑ i = 1 ⌊ x t ⌋ ∑ j = 1 ⌊ y t ⌋ i j \sum\limits_{i=1}^{\lfloor \frac{x}{t}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{y}{t}\rfloor}ij i=1∑⌊tx⌋j=1∑⌊ty⌋ij ,我们可以应用数论分块进行处理,而对于前半部分的 μ ( t ) t 2 \mu(t)t^2 μ(t)t2 ,我们可以预处理其的前缀和存放在数组 s s s,这样 ∑ t ⌊ n ⌊ n t ⌋ ⌋ μ ( t ) t 2 = s [ ⌊ n ⌊ n t ⌋ ⌋ ] − s [ t − 1 ] \sum\limits_t^{\lfloor\frac{n}{\lfloor\frac{n}{t}\rfloor}\rfloor}\mu(t)t^2=s[\lfloor\frac{n}{\lfloor\frac{n}{t}\rfloor}\rfloor]-s[t-1] t∑⌊⌊tn⌋n⌋μ(t)t2=s[⌊⌊tn⌋n⌋]−s[t−1] 。
设原式为 g ( x , y ) ( x ≤ y ) g(x,y)\space(x\leq y) g(x,y) (x≤y) ,那么原式: g ( x , y ) = ∑ d = 1 x d f ( ⌊ x d ⌋ , ⌊ y d ⌋ ) g(x,y)=\sum\limits_{d=1}^xdf(\lfloor\frac{x}{d}\rfloor,\lfloor\frac{y}{d}\rfloor) g(x,y)=d=1∑xdf(⌊dx⌋,⌊dy⌋) 。此时可以 O ( x + y ) O(x+y) O(x+y) 求出函数 g ( x , y ) g(x,y) g(x,y) 的值。
下面是AC代码。
#include
#include
#include
using namespace std;
int N;
const int M=20101009;
vector<int> prime,part,mu,s;
void init(){
s=part=vector<int>(N,0);
mu=vector<int>(N,-1);
s[1]=mu[1]=1;
for(int i=2;i<N;++i){
s[i]=((mu[i]*i*i)%M+M+s[i-1])%M;
if(!part[i]){
prime.push_back(i);
part[i]=i;
}
for(auto j:prime){
if(i*j>=N) break;
part[i*j]=j;
if(i%j==0){
mu[i*j]=0;
break;
}else mu[i*j]=-mu[i];
}
}
}
int f(int x,int y){
if(x>y) swap(x,y);
int res=0;
for(int l=1,r;l<=x;l=r+1){
r=min(x/(x/l),y/(y/l));
int t1=(((x/l)*(x/l+1))>>1)%M,t2=(((y/l)*(y/l+1))>>1)%M,t3=((s[r]-s[l-1])%M+M)%M;
res=(res+t1*(t2*t3%M)%M)%M;
}
return res;
}
int g(int x,int y){
if(x>y) swap(x,y);
int res=0;
for(int l=1,r;l<=x;l=r+1){
r=min(x/(x/l),y/(y/l));
res=(res+((((((r-l+1)*(l+r)>>1)%M))%M)*f(x/l,y/l))%M)%M;
}
return res;
}
signed main(){
int n,m;
cin>>n>>m;
N=max(n,m)+5;
init();
cout<<g(n,m)<<endl;
}