[题解] AGC038C

我不明白这题为什么要莫比乌斯反演

题意

\(\sum_{i< j}\operatorname{lcm}\left(a_i,a_j\right)\),且 \(a_i\le10^6\)

解答

\[\begin{aligned} f\left(x\right)&=\sum_{i=1}^n\sum_{j=i+1}^{n}a_ia_j\left[x \mid \gcd\left(a_i,a_j\right)\right]\\ &=\sum_{i=1}^n\sum_{j=i+1}^{n}\left(a_i\left[x\mid a_i\right]\right)\left(a_j\left[x\mid a_j\right] \right) \\ &=\dfrac{1}{2}\cdot\left(\left(\sum_{x\mid i}^{n}a_i\right)^2-\sum_{x\mid i}^{n}a_i^2\right) \\ g\left(x\right)&=\sum_{i=1}^n\sum_{j=i+1}^{n}a_ia_j\left[ \gcd\left(a_i,a_j\right)=x\right] \\ &=\sum_{i=1}^n\sum_{j=i+1}^{n}a_ia_j\left[x \mid \gcd\left(a_i,a_j\right)\right]-\sum_{k>x,x\mid k}^A\sum_{i=1}^n\sum_{j=i+1}^{n}a_ia_j\left[\gcd\left(a_i,a_j\right)=k\right] \\ &=f\left(x\right)-\sum_{k>x,x\mid k}^Ag\left(k\right) \end{aligned} \]

则从小到大枚举 \(x\) 即可计算出所有的 \(f\)\(g\),时间复杂度为 \(\sum_{i=1}^A\dfrac{A}{i}+\mathcal{O}\left(n\right)=\mathcal{O}\left(A\ln A+n\right)\),答案为

\[\begin{aligned} \sum_{i=1}^n\sum_{j=i+1}^{n}\operatorname{lcm}\left(a_i,a_j\right)&=\sum_{i=1}^n\sum_{j=i+1}^{n}\dfrac{a_ia_j}{\gcd\left(a_i,a_j\right)}\\ &=\sum_{d\ge1}\sum_{i=1}^n\sum_{j=i+1}^{n}\dfrac{a_ia_j}{d}\left[\gcd\left(a_i,a_j\right)=d\right]\\ &=\sum_{d\ge1}\dfrac{g\left(x\right)}{d} \end{aligned} \]

代码

#include <algorithm>
using namespace std;
typedef long long ll;
constexpr int N=200010,K=1000010,p=998244353;
int inv[K],sum[K],a[N],n,cnt[K];
int main(){
    scanf("%d",&n);for(int i=1;i<=n;++i) scanf("%d",&a[i]),++cnt[a[i]];
    inv[1]=1;for(int i=2;i<K;++i) inv[i]=1ll*(p-p/i)*inv[p%i]%p;
    int ans=0;
    for(int i=K-1;i;--i){
        int s1=0,s2=0;
        for(int j=i;j<K;j+=i) s1=(s1+1ll*cnt[j]*j%p)%p,s2=(s2+1ll*cnt[j]*j%p*j%p)%p;
        sum[i]=1ll*(1ll*s1*s1%p-s2+p)*inv[2]%p;
        for(int j=(i<<1);j<K;j+=i) sum[i]=(sum[i]-sum[j]+p)%p;
        // if(i<10) printf("%d %d %d %d %d\n",i,sum[i],s1,s2,inv[i]);
        ans=(ans+1ll*inv[i]*sum[i]%p)%p;
    }
    printf("%d\n",ans);
    return 0;
}

posted @ 2021-10-15 19:48  aixiaoyaowudi  阅读(62)  评论(0编辑  收藏  举报