[AGC038C] LCMs

\(\text{Problem}:\)LCMs

\(\text{Solution}:\)

首先令下标中的 \(i,j\) 都等于 \(1\),得到:

\[ans\times 2=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\text{lcm}(a_{i},a_{j})-\sum\limits_{i=1}^{n}a_{i} \]

现在只需要快速算出前面两层循环的答案。套路的,考虑把 \(\text{lcm}\)\(\gcd\) 表示并提取 \(d\),有:

\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\frac{a_{i}\times a_{j}}{\gcd(a_{i},a_{j})}=\sum\limits_{d=1}^{V}\frac{1}{d}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[\gcd(a_{i},a_{j})=d](a_{i}\times a_{j}) \]

然后将后面变为 \([\gcd(\frac{a_{i}}{d},\frac{a_{j}}{d})=1]\) 的形式并进行莫比乌斯反演,有:

\[\begin{aligned} &\sum\limits_{d=1}^{V}\frac{1}{d}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}(a_{i}\times a_{j})[d\mid a_{i}][d\mid a_{j}]\sum\limits_{dk\mid a_{i},dk\mid a_{j}}\mu(k)\\ &=\sum\limits_{d=1}^{V}\frac{1}{d}\sum\limits_{k=1}^{\lfloor\frac{V}{d}\rfloor}\mu(k)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}([dk\mid a_{i}]a_{i})\times ([dk\mid a_{j}]a_{j})\\ &=\sum\limits_{d=1}^{V}\frac{1}{d}\sum\limits_{k=1}^{\lfloor\frac{V}{d}\rfloor}\mu(k)\left(\sum\limits_{i=1}^{n}a_{i}[dk\mid a_{i}]\right)^{2} \end{aligned} \]

现在问题转化为对每个 \(k\)​,求出 \(f(k)=\sum\limits_{i=1}^{n}a_{i}[k\mid a_{i}]\)​。发现 \(a_{i}\) 值域很小,可以开桶记录,然后利用调和级数的性质暴力求出 \(f(k)\) 即可。总时间复杂度 \(O(V\log V)\)​。

\(\text{Code}:\)

#include <bits/stdc++.h>
//#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=1000010, Mod=998244353;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,a[N+5],pri[N],cnt,book[N+5],mu[N+5],f[N+5],iiv[N+5],ans;
inline void Init()
{
	mu[1]=1;
	for(ri int i=2;i<=N;i++)
	{
		if(!book[i]) pri[++cnt]=i, mu[i]=-1;
		for(ri int j=1;j<=cnt&&i*pri[j]<=N;j++)
		{
			book[i*pri[j]]=1;
			if(i%pri[j]) mu[i*pri[j]]=-mu[i];
			else break;
		}
	}
	for(ri int i=1;i<=N;i++)
	{
		for(ri int j=i;j<=N;j+=i)
		{
			f[i]=(f[i]+1ll*j*a[j]%Mod)%Mod;
		}
	}
}
signed main()
{
	n=read();
	for(ri int i=1;i<=n;i++)
	{
		int x=read();
		a[x]++;
	}
	Init();
	iiv[1]=1;
	for(ri int i=2;i<=N;i++) iiv[i]=1ll*(Mod-Mod/i)*iiv[Mod%i]%Mod;
	for(ri int i=1;i<=N;i++)
	{
		int res=0;
		for(ri int j=1;j<=N/i;j++)
		{
			if(!mu[j]) continue;
			if(~mu[j]) res=(res+1ll*f[i*j]*f[i*j]%Mod)%Mod;
			else res=(res-1ll*f[i*j]*f[i*j]%Mod+Mod)%Mod;
		}
		ans=(ans+1ll*res*iiv[i]%Mod)%Mod;
	}
	for(ri int i=1;i<=N;i++) ans=(ans-1ll*a[i]*i%Mod+Mod)%Mod;
	printf("%d\n",(int)(1ll*ans*(Mod+1)/2%Mod));
	return 0;
}
posted @ 2021-08-11 20:29  zkdxl  阅读(34)  评论(0编辑  收藏  举报