[SDOI2015]约数个数和,洛谷P3327,莫比乌斯反演+约数定理?

本文深入探讨了质因数分解在算法优化中的应用,通过解析特定数学问题,介绍了如何利用质因数分解和约数性质来简化复杂度高的算法,实现高效计算。文章详细解释了算法背后的数学原理,并提供了C++代码实现,展示了如何预处理和分块计算以提高效率。

正题

      题目链接点这里

      题目了然:

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

      但我们知道d(ij)=\sum_{x\mid i}\sum_{y\mid j} [gcd(x,y)=1]

      为什么呢?

      我们直到假如ij=p_1^{k_1}*...*p_m^{k_m}

      那么约数个数和就是\prod_{i=1}^m k_i+1

      考虑产生贡献的x,y是什么样子的:要不x不含a质因子,y含质因子;要不x含a质因子,y不含,要么两个都不含。

      假设i里面是a质因子的指数为x,j里面a质因子的指数为y,那么a质因子产生的贡献就为x+y+1,就等于k+1

      根据乘法原理,算出来的数就是\prod_{i=1}^m k_i+1

      那么式子就变成了

      \sum_{i=1}^n\sum_{j=1}^m\sum_{x\mid i}\sum_{y\mid j}[gcd(x,y)=1] \\=\sum_{i=1}^n\sum_{j=1}^m\sum_{x\mid i}\sum_{y\mid j}\sum_{d\mid gcd(x,y)} \mu(d)\\=\sum_{d=1}^n\mu(d)\sum_{d\mid x}\sum_{d\mid y} \frac{n}{x}\frac{m}{x}\\=\sum_{d=1}^n\mu(d)\sum_{d\mid x}\frac{n}{x}\sum_{d\mid y}\frac{m}{x}

      然后发现后面的东西其实是非常规律的\sum_{d\mid x} \frac{n}{x},其实就等于[1,\frac{n}{d}]的约数个数和。

      预处理一下,然后分块就行了。

      

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

int T,n,m;
const int maxn=50000;
int mu[maxn+10],mu_sum[maxn+10];
int d[maxn+10],d_sum[maxn+10];
int p[maxn+10],temp;
bool vis[maxn+10];

int main(){
	scanf("%d",&T);
	mu_sum[1]=mu[1]=1;vis[1]=true;
	for(int i=2;i<=maxn;i++){
		if(!vis[i]) {p[++p[0]]=i;mu[i]=-1;}
		for(int j=1;j<=p[0] && (temp=i*p[j])<=maxn;j++){
			vis[temp]=true;
			if(i%p[j]==0) break;
			mu[temp]=-mu[i];
		}
		mu_sum[i]=mu_sum[i-1]+mu[i];
	}
	for(int i=1;i<=maxn;i++){
		for(int j=i;j<=maxn;j+=i) d[j]++;
		d_sum[i]=d_sum[i-1]+d[i];
	}
	long long ans=0;
	while(T--){
		scanf("%d %d",&n,&m);
		int l=1,r;
		if(n>m) swap(n,m);
		ans=0;
		while(l<=n){
			r=min(n/(n/l),m/(m/l));
			ans+=(long long)d_sum[n/l]*d_sum[m/l]*(mu_sum[r]-mu_sum[l-1]);
			l=r+1;
		}
		printf("%lld\n",ans);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值