1358. 约数个数和

题目链接

1358. 约数个数和

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

\(\sum_{i=1}^N\sum_{j=1}^Md(ij)\)

输入格式

输入多组测试数据。

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

接下来的 \(T\) 行,每行两个整数 \(N、M\)

输出格式

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

数据范围

\(1 \le N,M,T \le 50000\)

输入样例:

2
7 4
5 6

输出样例:

110
121

解题思路

莫比乌斯反演

结论:\(d(i j)=\sum_{x \mid i} \sum_{y \mid j}[\operatorname{gcd}(x, y)=1]\)
证明:\(i,j\) 分别分解质因数:\(i=p_{1}^{\alpha_{1}} \cdots p_{k}^{\alpha_{k}}, j=p_{1}^{\beta_{1}} \cdots p_{k}^{\beta_{k}}, i \times j=p_{1}^{\alpha_{1}+\beta_{1}} \cdots p_{k}^{\alpha_{k}+\beta_{k}}\),对于 \(p_1\) 来说,要使 \(x \mid i,y \mid j\)\(gcd(x,y) =1\),则共有 \(\alpha_{1}+\beta_{1}+1\) 种选择,由于 \(p_i\) 之间相互独立,每种 \(p_i\)\(\alpha_{i}+\beta_{i}+1\) 种选择,从这些选择中各选择一个即可组成满足要求的数,共 \(\left(\alpha_{1}+\beta_{1}+1\right) \cdots\left(\alpha_{k}+\beta_{k}+1\right)\) 种方案,该式正好为约数个数

\(f(n)=\sum_{i=1}^{N} \sum_{j=1}^{M} \sum_{x \mid i} \sum_{y \mid j}[\operatorname{gcd}(x, y)=n]\),则由莫比乌斯反演第二条定理,得 \(F(n)=\sum_{i=1}^{N} \sum_{j=1}^{M} \sum_{x \mid i} \sum_{y \mid j}[n \mid \operatorname{gcd}(x, y)]\),考虑化简 \(F(n)\),将内层两重循环换到外面,\(x,y\) 范围分别为 \([1,N],[1,M]\),此时要求 \(x \mid i,y \mid j\),而 \([n \mid \operatorname{gcd}(x, y)]\) 只与 \(x,y\) 有关,此时范围内 \(x\) 的倍数有 \(N/x\) 个,\(y\) 的倍数有 \(M/y\) 个,\(F(n)=\sum_{x=1}^{N} \sum_{y=1}^{M}(N/x)\times (M/y)\times [n \mid \operatorname{gcd}(x, y)]\)\(x,y\) 都为 \(n\) 的倍数,设 \(x'=x/n,y'=y/n\)\(F(n)=\sum_{x'=1}^{N/n} \sum_{y'=1}^{M/n}(N/(x'n))\times (M/(y'n))\),令 \(N=N/n,M=M/n,x=x',y=y'\),得 \(F(n)=\sum_{x=1}^{N} \sum_{y=1}^{M}(N/x)\times (M/y)=\sum_{x=1}^{N}(N/x)\times \sum_{y=1}^{M}(M/y)\),设 \(H(x)=\sum_{i=1}^{x}(x/i)\),则 未变换之前,\(F(n)=H(N/n)\times H(M/n)\),而求解 \(H(x)\) 可整除分块 \(O(n\sqrt{n})\) 预处理出来,由莫比乌斯反演,\(f(n)=\sum_{n \mid d} \mu\left(\frac{d}{n}\right) F(d)=\sum_{n \mid d} \mu\left(\frac{d}{n}\right)\times H(N/d)\times H(M/d)\),而题目要求求解 \(f(1)\),则 \(f(1)=\sum_{ d} \mu\left(d\right)\times H(N/d)\times H(M/d)\),其中 \(d\) 为正整数,同时也可整除分块 \(O(\sqrt{n})\) 求解该式

  • 时间复杂度:\(O(n\sqrt{n})\)

代码

// 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;
}
posted @ 2022-06-29 16:15  zyy2001  阅读(33)  评论(0编辑  收藏  举报