ICode9

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

SP20173 题解

2022-06-09 21:02:40  阅读:160  来源: 互联网

标签:SP20173 end int 题解 sum mu aligned sigma


题解

提供一个贝尔级数爆拆 \(\sigma_0(n^2)\) 的做法(贝尔级数可见 command_block 的博客 Part. 2)。

设函数 \(f(n)=\sigma_0(n^2)\),不难证明这是一个积性函数:

对于 \(p\bot q\),\(f(p)f(q)=\sigma_0(p^2)\sigma_0(q^2)=\sigma_0((pq)^2)=f(pq)\),且 \(f(1)=1\)。

对于积性函数,就可以写出其贝尔级数:

\[\begin{array}{c} f(1)=1\\ f(p)=\sigma_0(p^2)=3\\ f(p^2)=\sigma_0(p^4)=5\\ \vdots\\ f(p^k)=\sigma_0(p^{2k})=2k+1\\ \vdots \end{array} \]

不难看出是一个等差数列。

记 \(f'(x)\) 为积性函数 \(f(x)\) 的贝尔级数。

\[f'(x)=\sum_{k=0}^{\infty}(2k+1)x^{k} \]

用生成函数基本操作:

\[\begin{aligned} f'(x)&=\sum_{k=0}^\infty(2k+1)x^k\\ f'(x)x&=\sum_{k=1}^\infty (2k-1)x^k\\ f'(x)(1-x)&=1+\sum_{k=1}^\infty 2x^k=g(x)\\ g(x)-g(x)x&=1+x\\ g(x)&=\frac{1+x}{1-x}=f'(x)(1-x)\\ f'(x)&=\frac{1+x}{(1-x)^2} \end{aligned} \]

众所周知,\(\mu^2(x)\) 的贝尔级数为 \(1+x\),\(1(x)\) 的贝尔级数为 \(\frac{1}{1-x}\)。

这里的 \(1(x)\) 指 \(\mu^{-1}(x)\),即 \((1*\mu)(x)=\epsilon(x)\),其中 \(*\) 表示迪利克雷卷积运算。

于是,\(f(x)=\mu^2*1*1\)。记 \(h(x)=\mu^2*1\):

\[\begin{aligned} \sum_{T=1}^nf(T)&=\sum_{T=1}^n\sum_{d\mid T}h(d)\\ &=\sum_{d=1}^nh(d)\lfloor\frac{n}{d}\rfloor \end{aligned} \]

对这个东西数论分块搞一搞,求 \(h(n)\) 的前缀和即可。

于是开始疯狂套用杜教筛:

\[\begin{aligned} \sum_{T=1}^nh(T)&=\sum_{T=1}^n\sum_{d\mid T}\mu^2(d)\\ &=\sum_{d=1}^n\mu^2(d)\lfloor\frac{n}{d}\rfloor \end{aligned} \]

快速求 \(\mu^2(n)\) 的前缀和即可(此步快速求 \(\mu^2(n)\) 前缀和可见)。

\[\begin{aligned} \sum_{T=1}^n\mu^2(T)&=\sum_{T=1}^n\sum_{d^2\mid T}\mu(d)\\ &=\sum_{d=1}^{\sqrt{n}}\mu(d)\lfloor\frac{n}{d^2}\rfloor \end{aligned} \]

关于时间复杂度:

image-20220316193431780.png

预处理处 \(f(n)\)、\(h(n)\)、\(\mu^2(n)\)、\(\mu(n)\) 的前 \(n^{\frac{2}{3}}\) 项的前缀和,加上杜教筛即可,时间复杂度 \(\mathcal O(n^\frac{2}{3})\)。

关于 \(h(n)\) 的线性筛:

\[\begin{aligned} h(p^k) &= (\mu^2*1)(p^k)\\ &= \sum_{i=0}^k\mu^2(p^i)\\ &=\sum_{i=0}^{\min(1, k)}\mu^2(p^i)\\ &=\min(2,k+1) \end{aligned} \]

关于 \(f(n)\) 的线性筛:

\[\begin{aligned} f(p^k) &= (\mu^2*1*1)(p^k)\\ &= (\mu^2*\sigma_0)(p^k)\\ &= \sum_{i=0}^{\min(1,k)}\sigma_0(p^i) \end{aligned} \]

关于 \(\sigma_0(p^k)\),显然有 \(\sigma_0(p^k)=k+1\)。

关于线性筛,在筛的时候若出现 i%prime[j] == 0 的情况,i * prime[j] 的最小质因数幂次必然大于等于 \(2\),可以省去上面 \(\sum\) 中的 \(\min\)。详见代码中 if(i%pr[j] == 0) 部分。

最后注意一下第一个点的时限为 1s,如果仍进行大规模预处理可能会 TLE。

参考实现

// Problem: SP20173 DIVCNT2 - Counting Divisors (square)
// From: Luogu
// URL: https://www.luogu.com.cn/problem/SP20173
// Time: 2022-03-16 19:39
// Author: lingfunny

#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define LL long long
#define UL unsigned long long
using namespace std;
using namespace __gnu_pbds;
const int mxz = 7.7e7+100;
unsigned int mu2[mxz];
UL h[mxz], f[mxz];
int pr[(int)1e7], tot, mu[mxz], t, mxn;
LL ask[(int)1e7];
short flg[mxz];
inline int mi(int p, short c) {
	int res = 1;
	while(c) { if(c&1) res *= p; p *= p; c >>= 1; }
	return res;
}
inline void Get() {
	mu[1] = f[1] = h[1] = mu2[1] = 1;
	for(int i = 2; i < mxn; ++i) {
		if(!flg[i]) pr[++tot] = i, mu[i] = -1, flg[i] = 1, h[i] = 2, f[i] = 3;
		for(int j = 1; j <= tot && pr[j] * i < mxn; ++j) {
			int v = i * pr[j];
			if(i%pr[j] == 0) {
				flg[v] = flg[i] + 1;
				// 最小质因数幂次至少为 2
				h[v] = h[v/mi(pr[j], flg[v])]<<1;
				f[v] = f[v/mi(pr[j], flg[v])] * (flg[v]+flg[v]+1);
				break;
			}
			flg[v] = 1;
			mu[v] = -mu[i];
			h[v] = h[i] << 1;
			f[v] = f[i] * 3;
		}
	}
	for(int i = 1; i < mxn; ++i) {
		mu2[i] = mu[i] * mu[i];
		mu2[i] += mu2[i-1];
		h[i] += h[i-1];
		f[i] += f[i-1];
	}
}
gp_hash_table <LL, UL> qh, qf, qm;
inline UL Qm(LL n) {
	if(n < mxn) return mu2[n];
	if(qm.find(n) != qm.end()) return qm[n];
	UL res = 0;
	for(int d = 1; (LL)d*d <= n; ++d)
	res += mu[d] * (n/((LL)d*d));
	qm[n] = res;
	return res;
}
inline UL Qh(LL n) {
	if(n < mxn) return h[n];
	if(qh.find(n) != qh.end()) return qh[n];
	register UL res = 0, pre = 0, cur = 0;
	for(register LL l = 1, r; l <= n; l = r + 1) {
		r = n/(n/l);
		cur = Qm(r);
		res += (cur-pre) * (n/l);
		pre = cur;
	}
	qh[n] = res;
	return res;
}
inline UL Qf(LL n) {
	if(n < mxn) return f[n];
	if(qf.find(n) != qf.end()) return qf[n];
	register UL res = 0, pre = 0, cur = 0;
	for(register LL l = 1, r; l <= n; l = r + 1) {
		r = n/(n/l);
		cur = Qh(r);
		res += (cur-pre) * (n/l);
		pre = cur;
	}
	qf[n] = res;
	return res;
}

signed main() {
	Get();
	scanf("%d", &t);
	LL n = 0;
	for(int i = 1; i <= t; ++i) scanf("%lld", &ask[i]), n = max(n, ask[i]);
	if(n <= 1e4+10) mxn = 1e4+2;
	else mxn = mxz-100;
	Get();
	for(int i = 1; i <= t; ++i) printf("%llu\n", Qf(ask[i]));
	return 0;
}

标签:SP20173,end,int,题解,sum,mu,aligned,sigma
来源: https://www.cnblogs.com/lingfunny/p/16361136.html

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

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

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

ICode9版权所有