1358. 约数个数和

题目链接

1358. 约数个数和

d(x)x 的约数个数,给定 N,M,求

i=1Nj=1Md(ij)

输入格式

输入多组测试数据。

第一行,一个整数 T,表示测试数据的组数。

接下来的 T 行,每行两个整数 NM

输出格式

T 行,每行一个整数,表示你所求的答案。

数据范围

1N,M,T50000

输入样例:

2 7 4 5 6

输出样例:

110 121

解题思路

莫比乌斯反演

结论:d(ij)=xiyj[gcd(x,y)=1]
证明:i,j 分别分解质因数:i=p1α1pkαk,j=p1β1pkβk,i×j=p1α1+β1pkαk+βk,对于 p1 来说,要使 xi,yjgcd(x,y)=1,则共有 α1+β1+1 种选择,由于 pi 之间相互独立,每种 piαi+βi+1 种选择,从这些选择中各选择一个即可组成满足要求的数,共 (α1+β1+1)(αk+βk+1) 种方案,该式正好为约数个数

f(n)=i=1Nj=1Mxiyj[gcd(x,y)=n],则由莫比乌斯反演第二条定理,得 F(n)=i=1Nj=1Mxiyj[ngcd(x,y)],考虑化简 F(n),将内层两重循环换到外面,x,y 范围分别为 [1,N],[1,M],此时要求 xi,yj,而 [ngcd(x,y)] 只与 x,y 有关,此时范围内 x 的倍数有 N/x 个,y 的倍数有 M/y 个,F(n)=x=1Ny=1M(N/x)×(M/y)×[ngcd(x,y)]x,y 都为 n 的倍数,设 x=x/n,y=y/nF(n)=x=1N/ny=1M/n(N/(xn))×(M/(yn)),令 N=N/n,M=M/n,x=x,y=y,得 F(n)=x=1Ny=1M(N/x)×(M/y)=x=1N(N/x)×y=1M(M/y),设 H(x)=i=1x(x/i),则 未变换之前,F(n)=H(N/n)×H(M/n),而求解 H(x) 可整除分块 O(nn) 预处理出来,由莫比乌斯反演,f(n)=ndμ(dn)F(d)=ndμ(dn)×H(N/d)×H(M/d),而题目要求求解 f(1),则 f(1)=dμ(d)×H(N/d)×H(M/d),其中 d 为正整数,同时也可整除分块 O(n) 求解该式

  • 时间复杂度:O(nn)

代码

// Problem: 约数个数和 // Contest: AcWing // URL: https://www.acwing.com/problem/content/1360/ // Memory Limit: 64 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=5e4+5; int t,n,m,prime[N],cnt,v[N],u[N],s[N],h[N]; int g(int a,int b) { return a/(a/b); } void init(int n) { u[1]=1; for(int i=2;i<=n;i++) { if(v[i]==0) { u[i]=-1; prime[++cnt]=v[i]=i; } for(int j=1;j<=cnt&&i*prime[j]<=n;j++) { if(v[i]<prime[j])break; if(i%prime[j]==0)u[i*prime[j]]=0; else u[i*prime[j]]=-u[i]; v[i*prime[j]]=prime[j]; } } for(int i=1;i<=n;i++)s[i]=s[i-1]+u[i]; for(int i=1;i<=n;i++) { for(int l=1,r;l<=i;l=r+1) { r=g(i,l); h[i]+=(r-l+1)*(i/l); } } } int main() { init(N-1); cin>>t; while(t--) { cin>>n>>m; LL res=0; int sz=min(n,m); for(int l=1,r;l<=sz;l=r+1) { r=min(g(n,l),g(m,l)); res+=1ll*(s[r]-s[l-1])*h[n/l]*h[m/l]; } cout<<res<<'\n'; } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16423901.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示