ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【数论】[SDOI2015]约数个数和

2021-06-01 13:36:21  阅读:204  来源: 互联网

标签:约数 lfloor frac 数论 sum rfloor mu int SDOI2015


传送门:
https://www.luogu.com.cn/problem/P3327
https://www.acwing.com/problem/content/1360/

莫比乌斯反演 + 整除分块

分析

首先,我们给出一个结论:

\[d(ij) = \sum_{x|i} \sum_{y|j} [(x, y) = 1] \]

证明:

设 \(i\) 的分解式为 \(i = \prod p_k^{\alpha_k}\) ,类似地,\(j = \prod p_k^{\beta_k}\)

对于质数 \(p_k\) ,\(ij\) 对应的因数个数为 \(\alpha_k + \beta_k + 1\)

而对于右式,\(p_k\) 如果想要产生贡献,那么只可能是:\(x, y\) 不同时存在因数 \(p_k\),注意到对应的贡献数即为 \(\alpha_k + \beta_k + 1\)

因此,由乘法原理,所求证式成立。

为了防止混淆,我们将题面中的 \(n, m\) 记为 \(N, M\)

由上述结论,题目的式子转化为:

\[\sum_{i=1}^N \sum_{j=1}^M \sum_{x|i} \sum_{y|j} [(x, y) = 1] \]

莫比乌斯反演:若 \(F(n) = \sum_{n|d}f(d)\),则有 \(f(n) = \sum_{n|d} \mu(\frac{d}{n})F(d)\)

于是我们设 \(f(n) = \sum_{i=1}^N \sum_{j=1}^M \sum_{x|i} \sum_{y|j} [(x, y) = n]\) ,对应的 \(F(n) = \sum_{i=1}^N \sum_{j=1}^M \sum_{x|i} \sum_{y|j} [n | (x, y)]\)

下面对 \(F(n)\) 进行变换:

\(F(n) \\= \sum_{i=1}^N \sum_{j=1}^M \sum_{x|i} \sum_{y|j} [n | (x, y)] \\ = \sum_{x=1}^N \sum_{y=1}^M \lfloor \frac{N}{x} \rfloor \lfloor \frac{M}{y} \rfloor [n | (x, y)] \\\)

设 \(x' = \lfloor \frac{x}{n} \rfloor ~, y'=\lfloor \frac{y}{n} \rfloor ~ , N'=\lfloor \frac{N}{n} \rfloor ~ , M'=\lfloor \frac{M}{n} \rfloor\) ,进而有

\(F(n) \\= \sum_{x=1}^{N'} \sum_{y=1}^{M'} \lfloor \frac{N'}{x'} \rfloor \lfloor \frac{M'}{y'} \rfloor \\ = \sum_{x=1}^{N'} \lfloor \frac{N'}{x'} \rfloor \sum_{y=1}^{M'} \lfloor \frac{M'}{y'} \rfloor\)

记 \(h(x) = \sum_{i=1}^x \lfloor \frac{x}{i} \rfloor\) ,\(h(x)\) 可用整除分块处理。

由莫比乌斯反演,\(f(n) = \sum_{n|d} \mu(\frac{d}{n})F(d)\) ,我们只需求 \(f(1)\)

下面对 \(f(1)\) 进行变换:

\[f(1) = \sum_{d} \mu({d})F(d) = \sum_{d} \mu({d})h(\lfloor \frac{N}{d} \rfloor)h(\lfloor \frac{M}{d} \rfloor) \]

由整除分块知,\(h(\lfloor \frac{N}{d} \rfloor)h(\lfloor \frac{M}{d} \rfloor)\) 取值最多为 \(\sqrt{N} + \sqrt{M}\) 块,而对于每一块,可以用前缀和 \(O(1)\) 处理出对应的 \(\mu\) 值,因此整体的复杂度为 \(O(T(\sqrt{N} + \sqrt{M}))\)

细节见代码:

#include<bits/stdc++.h>
using namespace std;

const int S=50050;

int primes[S], cnt;
bool vis[S];
int mu[S], sum[S];
int h[S];

int g(int b, int l){
	return b/(b/l);
}

void init(){
	// init sum[]
	mu[1]=1;
	for(int i=2; i<S; i++){
		if(!vis[i]) primes[cnt++]=i, mu[i]=-1;
		for(int j=0; i*primes[j]<S; j++){
			vis[i*primes[j]]=true;
			if(i%primes[j]==0) break;
			mu[i*primes[j]]=-mu[i];
		}
	}
	for(int i=1; i<S; i++) sum[i]=sum[i-1]+mu[i];
	
	// init h[]
	for(int x=1; x<S; x++){
		int &v=h[x];
		for(int l=1, r; l<=x; l=r+1){
			r=min(x, g(x, l));
			v+=x/l*(r-l+1);
		}
	}
}

int solve(int N, int M){
	int res=0;
	
	int n=min(N, M);
	for(int l=1, r; l<=n; l=r+1){
		r=min(n, min(g(N, l), g(M, l)));
		res+=(sum[r]-sum[l-1])*h[N/l]*h[M/l];
	}
	return res;
}

int main(){
	int T; cin>>T;
	init();
	while(T--){
		int N, M; cin>>N>>M;
		cout<<solve(N, M)<<endl;
	}
	return 0;
}

标签:约数,lfloor,frac,数论,sum,rfloor,mu,int,SDOI2015
来源: https://www.cnblogs.com/Tenshi/p/14836786.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有