洛谷P1829 [国家集训队]Crash的数字表格 / JZPTAB
加强版:题面不变,包含多组数据,数据组数为 T T T, 1 ≤ T ≤ 1 0 4 1\leq T\leq 10^4 1≤T≤104
题目大意
给出 n , m n,m n,m,求 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) \sum\limits_{i=1}^n\sum\limits_{j=1}^m lcm(i,j) i=1∑nj=1∑mlcm(i,j)。有 T T T组数据, 1 ≤ T ≤ 1 0 4 1\leq T\leq 10^4 1≤T≤104。
题解
前置知识:莫比乌斯反演
不妨设 n ≤ m n\leq m n≤m。
题意即求
∑ i = 1 n ∑ j = 1 m i × j gcd ( i , j ) \sum\limits_{i=1}^n\sum\limits_{j=1}^m \dfrac{i\times j}{\gcd(i,j)} i=1∑nj=1∑mgcd(i,j)i×j
枚举 gcd \gcd gcd得
∑ d = 1 n ∑ i = 1 n ∑ j = 1 m i × j d [ gcd ( i , j ) = d ] \sum\limits_{d=1}^n\sum\limits_{i=1}^n\sum\limits_{j=1}^m\dfrac{i\times j}{d}[\gcd(i,j)=d] d=1∑ni=1∑nj=1∑mdi×j[gcd(i,j)=d]
稍作转换可得
∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i × j × [ gcd ( i , j ) = 1 ] \sum\limits_{d=1}^nd\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\sum\limits_{j=1}^{\lfloor\frac md\rfloor}i\times j\times[\gcd(i,j)=1] d=1∑ndi=1∑⌊dn⌋j=1∑⌊dm⌋i×j×[gcd(i,j)=1]
利用莫比乌斯函数的性质,可得
∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i × j ∑ k ∣ gcd ( i , j ) μ ( t ) \sum\limits_{d=1}^nd\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\sum\limits_{j=1}^{\lfloor\frac md\rfloor}i\times j\sum\limits_{k|\gcd(i,j)}\mu(t) d=1∑ndi=1∑⌊dn⌋j=1∑⌊dm⌋i×jk∣gcd(i,j)∑μ(t)
枚举 k k k得
∑ d = 1 n d ∑ k = 1 ⌊ n d ⌋ k 2 × μ ( k ) ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ m k d ⌋ i × j \sum\limits_{d=1}^nd\sum\limits_{k=1}^{\lfloor\frac nd\rfloor}k^2\times \mu(k)\sum\limits_{i=1}^{\lfloor\frac{n}{kd}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{kd}\rfloor}i\times j d=1∑ndk=1∑⌊dn⌋k2×μ(k)i=1∑⌊kdn⌋j=1∑⌊kdm⌋i×j
∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ m k d ⌋ i × j \sum\limits_{i=1}^{\lfloor\frac{n}{kd}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{kd}\rfloor}i\times j i=1∑⌊kdn⌋j=1∑⌊kdm⌋i×j可变为 ⌊ n k d ⌋ × ( ⌊ n k d ⌋ + 1 ) 2 × ⌊ n k d ⌋ × ( ⌊ n k d ⌋ + 1 ) 2 \dfrac{\lfloor\frac{n}{kd}\rfloor\times(\lfloor\frac{n}{kd}\rfloor+1)}{2}\times \dfrac{\lfloor\frac{n}{kd}\rfloor\times (\lfloor\frac{n}{kd}\rfloor+1)}{2} 2⌊kdn⌋×(⌊kdn⌋+1)×2⌊kdn⌋×(⌊kdn⌋+1)。设 g t ( k ) = k × ( k + 1 ) 2 gt(k)=\dfrac{k\times (k+1)}{2} gt(k)=2k×(k+1),则原式变为
∑ d = 1 n d ∑ k = 1 ⌊ n d ⌋ k 2 × μ ( k ) × g t ( ⌊ n k d ⌋ ) × g t ( ⌊ m k d ⌋ ) \sum\limits_{d=1}^nd\sum\limits_{k=1}^{\lfloor\frac nd\rfloor}k^2\times \mu(k)\times gt(\lfloor\dfrac{n}{kd}\rfloor)\times gt(\lfloor\dfrac{m}{kd}\rfloor) d=1∑ndk=1∑⌊dn⌋k2×μ(k)×gt(⌊kdn⌋)×gt(⌊kdm⌋)
令 T = k d T=kd T=kd,枚举 T T T,可得
∑ T = 1 n g t ( ⌊ n T ⌋ ) × g t ( ⌊ m T ⌋ ) ∑ k ∣ T T k × k 2 × μ ( k ) \sum\limits_{T=1}^ngt(\lfloor\dfrac{n}{T}\rfloor)\times gt(\lfloor\dfrac{m}{T}\rfloor)\sum\limits_{k|T}\dfrac{T}{k}\times k^2\times \mu(k) T=1∑ngt(⌊Tn⌋)×gt(⌊Tm⌋)k∣T∑kT×k2×μ(k)
整理可得
∑ T = 1 n g t ( ⌊ n T ⌋ ) × g t ( ⌊ m T ⌋ ) × T ∑ k ∣ T k × μ ( k ) \sum\limits_{T=1}^ngt(\lfloor\dfrac{n}{T}\rfloor)\times gt(\lfloor\dfrac{m}{T}\rfloor)\times T\sum\limits_{k|T} k\times \mu(k) T=1∑ngt(⌊Tn⌋)×gt(⌊Tm⌋)×Tk∣T∑k×μ(k)
现在的问题在于如何快速求出 ∑ k ∣ T k × μ ( k ) \sum\limits_{k|T} k\times \mu(k) k∣T∑k×μ(k)。设 f ( d ) = ∑ k ∣ d k × μ ( k ) f(d)=\sum\limits_{k|d} k\times \mu(k) f(d)=k∣d∑k×μ(k),我们发现 f ( d ) f(d) f(d)是一个积性函数,可以 O ( n ) O(n) O(n)预处理出。
将 g t ( k ) gt(k) gt(k)和 f ( d ) f(d) f(d)用 O ( n ) O(n) O(n)预处理出,每次询问用数论分块只需 O ( n ) O(\sqrt n) O(n),所以总时间复杂度为 O ( n + T n ) O(n+T\sqrt n) O(n+Tn)。
注:下面代码是有多组数据的,在洛谷上交时要去掉。
code
#include<bits/stdc++.h>
using namespace std;
const int N=10000000;
const long long mod=20101009;
int t,n,m,z[N+5],p[N+5];
long long ans,f[N+5];
long long gt(int t){
return 1ll*t*(t+1)/2%mod;
}
int main()
{
f[1]=1;
for(int i=2;i<=N;i++){
if(!z[i]){
p[++p[0]]=i;f[i]=(1-i+mod)%mod;
}
for(int j=1;j<=p[0]&&i*p[j]<=N;j++){
z[i*p[j]]=1;
if(i%p[j]==0){
f[i*p[j]]=f[i];
break;
}
f[i*p[j]]=f[i]*f[p[j]]%mod;
}
}
for(int i=1;i<=N;i++){
f[i]=(f[i-1]+i*f[i]%mod)%mod;
}
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
ans=0;
if(n>m) swap(n,m);
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=(ans+(f[r]-f[l-1]+mod)%mod*gt(n/l)%mod*gt(m/l)%mod)%mod;
}
printf("%lld\n",ans);
}
return 0;
}