NKOJP2468 Sum of LCM/luoguP3911 最小公倍数之和


题目:传送门

Problem

Solution

对于这种求多个\(\sum\)后面跟个\(gcd,lcm\)的式子一般都要用莫比乌斯反演。

想办法将式子化出\([n==1]\)形式

过程推导如下:

\(\sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(A_i,A_j)\)(以下\(n\)因为与\(A_i\)同阶,所以沿用)

\(=\sum_{i=1}^{n} \sum_{j=1}^{n}\mathrm{lcm}(i,j) \times cnt_i \times cnt_j\)

\(=\sum_{i=1}^{n} \sum_{j=1}^{n} \frac{i \times j}{gcd(i,j)} \times cnt_i \times cnt_j = \sum_{k=1}^{n}\sum_{i=1}^{n} \sum_{j=1}^{n} [gcd(i,j)==k] \frac{i \times j}{k} \times cnt_{i} \times cnt_{j}\)

\(=\sum_{k=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor} \sum_{j=1}^{\lfloor\frac{n}{k}\rfloor} [gcd(i,j)==1] \frac{ik \times jk}{k} \times cnt_{ik} \times cnt_{jk}\)

\(=\sum_{k=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor} \sum_{j=1}^{\lfloor\frac{n}{k}\rfloor} \sum_{d|gcd(i,j)} μ(d) \times \frac{ik \times jk}{k} \times cnt_{ik} \times cnt_{jk}\)

\(=\sum_{k=1}^{n}\sum_{d=1}^{\lfloor\frac{n}{k}\rfloor} \sum_{i=1}^{\lfloor\frac{n}{kd}\rfloor} \sum_{j=1}^{\lfloor\frac{n}{kd}\rfloor} μ(d) \times \frac{ikd \times jkd}{k} \times cnt_{ikd} \times cnt_{jkd}\)

\(=\sum_{k=1}^{n}\sum_{dk=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{i=1}^{\lfloor\frac{n}{dk}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{dk}\rfloor}μ(d) \times \frac{ikd \times jkd}{k} \times cnt_{ikd} \times cnt_{jkd}\)

\(T=dk\),则

\(=\sum_{k=1}^{n}\sum_{T=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{i=1}^{\lfloor\frac{n}{T}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{T}\rfloor}μ(\frac{T}{k}) \times \frac{iT \times jT}{k} \times cnt_{iT} \times cnt_{jT}\)

\(=\sum_{k=1}^{n}\sum_{T=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{i=1}^{\lfloor\frac{n}{T}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{T}\rfloor}μ(\frac{T}{k}) \times i \times j \times T \times \frac{T}{k} \times cnt_{iT} \times cnt_{jT}\)

\(=\sum_{T=1}^{n}T\sum_{d|T}μ(d) \times d (\sum_{i=1}^{\lfloor\frac{n}{T}\rfloor} cnt_{iT} \times i)^2\)

预处理出\(f[T]=\sum_{d|T}μ(d) \times d\),最后暴力计算剩余部分即可。

时间复杂度\(O(n\sqrt n)\)

\(code:\)

#include
using namespace std;
typedef long long ll;
const int MAX_N = 50000 + 5;
int n,a[MAX_N],cnt[MAX_N];
int prime[MAX_N],isprime[MAX_N],tot,mu[MAX_N];
ll f[MAX_N],ans;
int main(){
	mu[1]=1;
	for(int i=2;i<=50000;i++){
		if(!isprime[i]){
			prime[++tot]=i;
			mu[i]=-1;
		}
		for(int j=1;j<=tot && i*prime[j]<=50000;j++){
			isprime[i*prime[j]]=1;
			if(i%prime[j]==0) break;
			mu[i*prime[j]]=-mu[i];
		}
	}
	for(int i=1;i<=50000;i++)
		for(int j=i;j<=50000;j+=i)
			f[j]+=1ll*i*mu[i];
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		cnt[a[i]]++;
	}
	for(int i=1;i<=50000;i++){
		ll tmp=0;
		for(int j=1;j<=50000/i;j++) tmp+=1ll*cnt[i*j]*j;
		ans+=1ll*i*f[i]*tmp*tmp;
	}
	printf("%lld\n",ans);
	return 0;
}