YbtOJ#943-平方约数【莫比乌斯反演,平衡规划】

1|0正题

题目链接:http://www.ybtoj.com.cn/contest/122/problem/3


1|1题目大意

S(i)表示i的约数个数,Q次询问给出n,m

a=1nb=1mS(a2)×S(b2)×S(a×b)

1Q104,1n,m2×105


1|2解题思路

前面的推式子挺套路的
首先我们要搞定S(n2)这个东西,一个经典的结论就是S(n×m)=i|nj|m[gcd(i,j)=1]。莫反一下就有

S(a×b)=d|(a×b)μ(d)i×d|aj×d|b1

所以就有

S(n2)=d|nμ(d)S(nd)2

用线性筛筛出前面的S,然后O(nlogn)求出h(n)=S(n2)

然后化一下式子

a=1nb=1mh(a)×h(b)i|aj|b[gcd(i,j)=1]

d=1μ(d)(d|ii|ah(a))(d|jj|bh(b))

d=1μ(d)(d|aS(ad)h(a))(d|bS(bd)h(b))

然后就好像没得化简了,先处理出F(d,n)=i=1nh(i×d)S(i)

发现d很大的时候后面那个东西的取值就很小,但是d很多,需要快速处理。

设定一个分界值T,每次小于T的部分我们就暴力用F数组计算,大于T的部分我们预处理出一个

G(d,i,j)=x=T+1dF(i)F(j)μ(d)

然后整除分块计算。

这里的kN23会平均一些,时间复杂度O(n43+Qn23)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #define ll long long using namespace std; const ll N=2e5+10,P=1<<30; ll q,n,m,cnt,pri[N],mu[N],S[N],sg[N],g[N],o[N]; vector<int>f[N],d[N]; bool v[N]; void prime(){ mu[1]=sg[1]=1; for(ll i=2;i<N;i++){ if(!v[i])pri[++cnt]=i,mu[i]=-1,g[i]=2,sg[i]=2; for(ll j=1;j<=cnt&&i*pri[j]<N;j++){ v[i*pri[j]]=1; if(i%pri[j]==0){ g[i*pri[j]]=g[i]+1; sg[i*pri[j]]=sg[i]/g[i]*g[i*pri[j]]; break; } mu[i*pri[j]]=-mu[i];g[i*pri[j]]=2; sg[i*pri[j]]=sg[i]*sg[pri[j]]; } } for(ll i=1;i<N;i++) for(ll j=i;j<N;j+=i) (S[j]+=sg[j/i]*sg[j/i]*mu[i]%P)%=P; return; } signed main() { freopen("math.in","r",stdin); freopen("math.out","w",stdout); prime(); scanf("%lld",&q);ll lim=2e5; ll T=(ll)pow(lim,2.0/3.0)+1; f[0].resize(lim+1); for(ll i=1;i<=lim;i++){ f[i].push_back(0); for(ll j=1;j<=lim/i;j++){ ll tmp=f[i][j-1]; f[i].push_back((tmp+S[i*j]*sg[j])%P); } } d[T].resize((lim/T)*(lim/T)+1); for(ll i=T+1;i<=lim;i++){ ll p=lim/i; d[i].resize(p*p+1); for(ll j=1,sum=0;j<=lim/i;j++) for(ll k=j;k<=lim/i;k++) d[i][(j-1)*p+k]=(d[i-1][(j-1)*o[i-1]+k]+f[i][j]*f[i][k]*mu[i])%P; o[i]=p; } while(q--){ scanf("%lld%lld",&n,&m); if(n>m)swap(n,m);ll ans=0; for(ll i=1;i<=min(T,n);i++) (ans+=1ll*f[i][n/i]*f[i][m/i]*mu[i]%P)%=P; for(ll l=T+1,r;l<=n;l=r+1){ r=min(n/(n/l),m/(m/l)); (ans+=d[r][(n/l-1)*o[r]+m/l]-d[l-1][(n/l-1)*o[l-1]+m/l])%=P; } printf("%lld\n",(ans+P)%P); } return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14436364.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(83)  评论(2编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示