LCM

首先

i=1ni=n(n+1)2

i=1ni2=n(n+1)(2n+1)6

i=1ni3=(i=1ni)2

P3911 最小公倍数之和

i=1nj=1nlcm(Ai,Aj)

观察值域,发现与 n 同阶,记 ci 表示数字 i 出现次数。

i=1nj=1nlcm(i,j)cicj

i=1nj=1nij(i,j)cicj

d=1ni=1nj=1nijdcicj[(i,j)=d]

d=1ndi=1ndj=1ndijcidcjd[(i,j)=1]

d=1ndi=1ndj=1ndijcidcjdk|(i,j)μ(k)

d=1ndk=1ndμ(k)k2i=1ndkj=1ndkijcidkcjdk

T=dk 枚举 T

T=1nTk|Tμ(k)k(i=1nTciTi)2

因为枚举 dk,而 k 是必须枚举的,所以可以省略掉 d。然后原来有 d=1nd,可以从后面找个 k 组成 T。

考虑枚举的是 T=dk,所以一定有 k|T.

最后预处理出 k|Tμ(k)k,暴力做(i=1nTciTi)2.

因为 i=1nni 这样子是个调和级数的形式,所以后面暴力是 O(nlnn)的。

Code

#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #define N (int)(5e4+5) #define int long long using namespace std; bool vis[N]; int pri[N],mu[N],sum[N],cnt; int n,a[N],c[N]; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)) { sum=(sum<<3)+(sum<<1)+ch-'0'; ch=getchar(); } return sum*f; } void pr(int x) { if(x<0) { putchar('-'); x=-x; } if(x>9) pr(x/10); putchar(x%10+'0'); } void get_mu() { mu[1]=1; for(int i=2;i<=N-5;i++) { if(!vis[i]) { mu[i]=-1; pri[++cnt]=i; } for(int j=1;j<=cnt&&pri[j]*i<=N-5;j++) { vis[pri[j]*i]=1; if(i%pri[j]==0) break; mu[pri[j]*i]=-mu[i]; } } } signed main() { get_mu(); n=rd(); int qwq=0; for(int i=1;i<=n;i++) { a[i]=rd(); qwq=max(qwq,a[i]); ++c[a[i]]; } for(int i=1;i<=qwq;i++) for(int j=i;j<=qwq;j+=i) sum[j]+=mu[i]*i; int ans=0; for(int T=1;T<=qwq;T++) { int ret=0; for(int i=1;i<=qwq/T;i++) ret+=i*c[i*T]; ret*=ret; ans+=T*ret*sum[T]; //cout<<ret<<endl; } pr(ans); return 0; }

较为困难的LCM

i=1nj=1nlcm(i,j)

n1010

那么我们没办法用 O(nlnn) 的办法了。

先化简下

i=1nj=1nij(i,j)

d=1ni=1nj=1nijd[(i,j)=d]

d=1ndi=1ndj=1ndij[(i,j)=1]

h(n)=i=1ni[(i,n)=1]

这个东西就等于(实际上是我 oeis 出来的)

nϕ(n)+[n=1]2

考虑证明下

已有 gcd(i,n)=1.

若有一个数 d,(d1) 使得 gcd(n,(ni))=d.

那么 n%d=0,(ni)%d=0i%d=0

那么 gcd(i,n)=d.

所以可得,已有 gcd(i,n)=1gcd(n,(ni))=1.

考虑 i,ni 成对出现,且对答案贡献是 n.

则去重后答案为 nϕ(n)+[n=1]2.

那么

ans=d=1ndi=1ndj=1ndij[(i,j)=1]

d=1ndi=1ndi2h(i)1

d=1ndi=1ndi2iϕ(i)+[i=1]21

d=1ndi=1ndi2ϕ(i)

因为 [i=1]1 抵消了。

S(n)=i=1ni2ϕ(i)

那么

ans=d=1ndS(nd)

f(x)=x2ϕ(x),g(x)=x2.

那么

(fg)(n)=d|nf(d)g(nd)=n3

这里省略的可以在这里找到

接下来就是杜教筛了。

最后整个 ans 来个整除分块。

Code

#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <map> #define N (int)(1.6e6) #define ll long long #define mod 1000000007 using namespace std; ll lrd() { ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } bool vis[N]; int pri[N>>2],tot=0; ll phi[N],inv6; map<ll,ll>ans_phi; ll fpow(ll x,ll y=mod-2) { ll res=1; while(y) { if(y&1) res=res*x%mod; x=x*x%mod; y>>=1; } return res; } void init() { phi[1]=1; for(int i=2;i<N;i++) { if(!vis[i]) pri[++tot]=i,phi[i]=i-1; for(int j=1;j<=tot&&pri[j]*i<N;j++) { vis[pri[j]*i]=1; if(i%pri[j]==0) { phi[i*pri[j]]=phi[i]*pri[j]; break; } phi[i*pri[j]]=phi[i]*phi[pri[j]]; } } for(int i=1;i<N;i++) phi[i]=(phi[i-1]+phi[i]*i%mod*i%mod)%mod; } ll SUM1(ll x) { x%=mod; return (x*(x+1)/2)%mod; } ll SUM2(ll x) { x%=mod; return x*(x+1)%mod*(2*x+1)%mod*inv6%mod; } ll SUM3(ll x) { return SUM1(x)*SUM1(x)%mod; } ll get_phi(ll x) { if(x<N) return phi[x]; if(ans_phi[x]) return ans_phi[x]; ll ans=SUM3(x); for(ll l=2,r;l<=x;l=r+1) { r=x/(x/l); ans-=(SUM2(r)-SUM2(l-1))*get_phi(x/l)%mod; ans%=mod; } return ans_phi[x]=ans; } int main() { init(); ll n; n=lrd(); inv6=fpow(6); ll ans=0; for(ll l=1,r;l<=n;l=r+1) { r=n/(n/l); ans+=(SUM1(r)-SUM1(l-1))*get_phi(n/l)%mod; ans%=mod; } ans=(ans%mod+mod)%mod; printf("%lld",ans); return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15872235.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(253)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示