ICode9

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

[SDOI2015]约数个数和

2021-01-08 13:33:12  阅读:202  来源: 互联网

标签:约数 frac limits cc sum 个数 rfloor int SDOI2015


题意

求\(\sum\limits_i^n\ \sum\limits_j^m\ d(ij)\)其中\(d(x)\)为\(x\)的约数个数

想法

看到这个柿子想到的就是莫反了。
有这样一个结论

\( d(xy)= \sum\limits_{i|x} \ \sum\limits_{j|y}[gcd(i,j) == 1]  \)

所以变形原柿子(n > m)

\(\sum\limits_i^n\ \sum\limits_j^m\ d(ij)\)

\(\sum\limits_i^n\ \sum\limits_j^m\ \sum\limits_{x|i} \ \sum\limits_{y|j}[gcd(x,y) == 1])\)

用\(\mu(x)\) 的性质:

\([n == 1] = \sum\limits_{d|n}\mu(d)\)

\(\sum\limits_i^n\ \sum\limits_j^m\ \sum\limits_{x|i} \ \sum\limits_{y|j}\sum\limits_{d|gcd(x,y)}\mu(d))\)

改为枚举\(d\)-

\(\sum\limits_{d = 1}^n\sum\limits_{x = 1}^{n/d}\sum\limits_{i = 1}^{n/d/x}\sum\limits_{y = 1}^{m/d}\sum\limits_{j = 1}^{m/d/y}\mu(d)\)

\(\sum\limits_{d = 1}^n\sum\limits_{x = 1}^{n/d}\lfloor\frac{n}{d * x}\rfloor\sum\limits_{y = 1}^{n/d}\lfloor\frac{m}{d * y}\rfloor\mu(d)\)

\(\sum\limits_{d = 1}^n\mu(d)\sum\limits_{x = 1}^{n/d}\lfloor\frac{\lfloor\frac{n}{d}\rfloor}{x}\rfloor\sum\limits_{y = 1}^{m/d}\lfloor\frac{\lfloor\frac{m}{d}\rfloor}{y}\rfloor\)

后面两个\(\sum\)可以整除分块

复杂度\(O(N\sqrt(N))\)

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
int read(){
	char cc = getchar(); int cn = 0, flus = 1;
	while(cc < '0' || cc > '9'){
    	if(cc == '-') flus = -flus;
		cc = getchar();
	}
	while(cc >= '0' && cc <= '9')
	    cn = cn * 10 + cc - '0', cc = getchar();
	return cn * flus;
}
const int N = 50000 + 5;
int u[N], sum[N], pm[N], n, f[N], top;
bool isp[N];
void init(){
	u[1] = 1;
	for(int i = 2; i <= n; i++){
		if(!isp[i]){
			pm[++top] = i;
			u[i] = -1;
		}
		for(int j = 1; j <= top; j++){
			int p = pm[j];
			if(p * i > n) break;
			if(i % p == 0){
				isp[p * i] = 1;
				break;
			}
			isp[p * i] = 1;
			u[p * i] = u[p] * u[i];
		}
	}
	int l, r;
	for(int i = 1; i <= n; i++){
		for(l = 1; l <= i; l = r + 1){
			r = i/(i/l);
			f[i] += (r - l + 1) * (i/l);
		}
		sum[i] = sum[i - 1] + u[i];
	}
}
int solve(int x, int y){
	if(x > y) swap(x, y);
	int ans = 0, l = 1, r;
	for(l = 1; l <= x; l = r + 1){
		r = min((x/(x/l)), (y/(y/l)));
		ans += (sum[r] - sum[l - 1]) * f[x/l] * f[y/l];
	}
	return ans;
}
signed main()
{
	n = 50000;
	init();
	int T = read(), a, b;
	while(T--){
		a = read(); b = read();
		printf("%lld\n", solve(a, b));
	}
	return 0;
}

标签:约数,frac,limits,cc,sum,个数,rfloor,int,SDOI2015
来源: https://www.cnblogs.com/dixiao/p/14250973.html

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

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

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

ICode9版权所有