博客园同步html
原题连接c++
前置知识:web
本题的弱化版app
不难发现,原来的:svg
i=1∑nj=1∑nlcm(i,j)spa
变成了:code
i=1∑nj=1∑nlcm(ai,aj)orm
一言不合就开始推式子。xml
考虑用
ci 表示
i 出现的次数,而后:htm
======i=1∑nj=1∑nlcm(ai,aj)i=1∑nj=1∑nlcm(i,j)×ci×cji=1∑nj=1∑ngcd(i,j)i×j×ci×cjd=1∑ni=1∑⌊dn⌋j=1∑⌊dn⌋[gcd(i,j)=1]d×i×j×cid×cjdd=1∑ni=1∑⌊dn⌋j=1∑⌊dn⌋k∣gcd(i,j)∑μ(k)×d×i×j×cid×cjdd=1∑nk=1∑⌊dn⌋i=1∑⌊kdn⌋j=1∑⌊kdn⌋μ(k)×d×i×j×k2×cidk×cjdkT=1∑nT×(i=1∑⌊Tn⌋i×ciT)2k∣T∑μ(k)×k
对于后面的:
k∣T∑μk×k
能够用
O(nlnn) 的时间完成预处理。
nlnn=i=1∑n⌊in⌋
而后,对中间那块暴力计算便可。
时间复杂度:
O(nlnn).
实际得分:
100pts.
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+1;
typedef long long ll;
inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}
inline void write(ll x) {
if(x<0) {putchar('-');write(-x);return;}
if(x<10) {putchar(char(x%10+'0'));return;}
write(x/10);putchar(char(x%10+'0'));
}
int n,c[N],mu[N],prime[N];
int cnt=0; bool h[N];
ll s[N],ans=0;
inline void Euler(int n) {
mu[1]=1; for(register int i=2;i<=n;i++) {
if(!h[i]) mu[i]=-1,prime[++cnt]=i;
for(register int j=1;j<=cnt && i*prime[j]<=n;j++) {
h[i*prime[j]]=1;
if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
mu[i*prime[j]]-=mu[i];
}
}
}
int main() {
n=read(); int maxi=0;
for(register int i=1,t;i<=n;i++) {t=read(); c[t]++; maxi=max(maxi,t);}
Euler(maxi); for(register int i=1;i<=maxi;i++)
for(register int j=i;j<=maxi;j+=i) s[j]+=1ll*mu[i]*i;
for(register int T=1;T<=maxi;T++) {
ll sum=0;
for(register int i=1;i<=maxi/T;i++) sum+=1ll*c[i*T]*i;
ans+=T*sum*sum*s[T];
} write(ans);
return 0;
}