[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;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。