【莫比乌斯反演】洛谷P3327 约数个数和 题解

本文介绍了如何利用莫比乌斯反演和整除分块技巧解决编程问题P2522,通过新定义函数处理约数个数计算,并给出了详细的步骤和C++代码实现。
摘要由CSDN通过智能技术生成

题目

定义d(x)表示x的约数个数,给定n,m,求:

$\sum_{i=1}^{n}\sum_{j=1}^{m}d(ij)$

思路

首先,新定义函数d没有特定的算法,因此需要对它做小小的处理。

易知,\forall i\in\mathbb{N^+}$ i=\prod_{p\in \mathbb{P}}p^{s_p}$$d(i)=\prod_{p\in\mathbb{P}}(s_p+1)$

则令:

\left\{\begin{matrix} & i=\prod_{p\in \mathbb{P}}p^{s_p}\\ & j=\prod_{p\in \mathbb{P}}p^{t_p}\end{matrix}\right.\wedge i\neq j

那么:

$ij=\prod_{p\in\mathbb{P}}p^{s_p+t_p}$

所以:

$d(ij)=\prod_{p\in\mathbb{P}}(s_p+t_p+1)$

考虑枚举$a|i,\: b|j$,此时考虑gcd(a,b)=1,则a,b中就不会有相同的质因子。

所以:

$d(ij)=\sum_{a|i}\sum_{b|j}[gcd(a,b)=1]$

带入原式得:

$\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{a|i}\sum_{b|j}[gcd(a,b)=1]$

带入莫比乌斯反演结论:

$\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{a|i}\sum_{b|j}\sum_{d|gcd(i,j)}\mu (d)$

$\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{a|i}\sum_{b|j}\sum_{d=1}^{min(n,m)}\mu (d)[d|gcd(a,b)]$

$\sum_{d=1}^{min(n,m)}\mu (d)\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{a|i}\sum_{b|j}[d|gcd(a,b)]$

到这里是不是很熟悉了?又可以用洛谷P2522 Problem b 的方法做了!详参上上篇题解:

【整除分块&莫比乌斯反演】洛谷P2522 Problem b-CSDN博客文章浏览阅读143次。显然两段区间所产生的的答案可以用容斥原理“归一”处理。个d的倍数,所以可以把后面两个大。处理,详参上一篇题解。https://blog.csdn.net/m0_60506105/article/details/136581761?spm=1001.2014.3001.5501继续欣赏推式子:

$\sum_{d=1}^{min(n,m)}\mu(d)\sum_{a=1}^{n}\sum_{b=1}^{m}[d|gcd(a,b)]\left \lfloor \frac{n}{a} \right \rfloor\left \lfloor \frac{m}{b} \right \rfloor$

$\sum_{d=1}^{min(n,m)}\mu(d)\sum_{a=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum_{b=1}^{\left \lfloor \frac{m}{d} \right \rfloor}\left \lfloor \frac{n}{da} \right \rfloor\left \lfloor \frac{m}{db} \right \rfloor$

$\sum_{d=1}^{min(n,m)}\mu(d)\sum_{a=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\left \lfloor \frac{n}{da} \right \rfloor\sum_{b=1}^{\left \lfloor \frac{m}{d} \right \rfloor}\left \lfloor \frac{m}{db} \right \rfloor$

到了这里,剩下的就交给整除分块了。

定义:

        $f(n)=\sum_{i=1}^{n}\left \lfloor \frac{n}{i} \right \rfloor$

则可以对此函数进行如处理,那么答案就是:

$\sum_{d=1}^{min(n,m)}\mu(d)f\left ( \left \lfloor \frac{n}{da} \right \rfloor \right )f\left ( \left \lfloor \frac{m}{db} \right \rfloor \right )$

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll z=1e6+9,N=5e4+9;
ll mu[z],p[z],np,xb[z],f[z];
bool isp[z];
ll T,n,m,ans;
void fastread()
{
	ios::sync_with_stdio(0);
}
void getmu()
{
	memset(isp,1,sizeof(isp));
	isp[1]=0;
	mu[1]=1;
	for(ll i=2;i<=N;i++)
	{
		if(isp[i])
		{
			p[++np]=i;
			mu[i]=-1;
		}
		for(ll j=1;j<=np&&i*p[j]<=N;j++)
		{
			ll x=i*p[j];
			isp[x]=0;
			if(i%p[j]!=0)mu[x]=-mu[i];
			else 
			{
				mu[x]=0;
				break;
			}
		}
	}
	for(int i=1;i<=N;i++)
	xb[i]=xb[i-1]+mu[i];
	for(int i=1;i<=N;i++)
	{
		ll res=0;
		for(int l=1,r;l<=i;l=r+1)
		{
			r=i/(i/l);
			res+=(r-l+1)*(i/l);
		}
		f[i]=res;
	}
}
ll cal(ll n,ll m)
{
	ll res=0,rr=min(n,m);
	for(int l=1,r;l<=rr;l=r+1)
	{
		r=min(n/(n/l),m/(m/l));
		res+=(xb[r]-xb[l-1])*f[n/l]*f[m/l];
	}
	return res;
}
int main()
{
	fastread();
	cin>>T;
	getmu();
	while(T--)
	{
		cin>>n>>m;
		ans=cal(n,m);
		cout<<ans<<endl;
	}
	return 0;
}

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值