【Luogu P3327】 [SDOI2015]约数个数和

链接:

洛谷

更好的观看体验

正文:

本题最大的难点就是怎么处理 \(d(ij)\)

假设在 \(ij\) 的一个约数中有 \(c\) 个 质因子 \(p\) 相乘(即 \(p^c\)),我们总是先取 \(i\) 中的 \(p\)\(i\) 中不够取再取 \(j\) 中的。

如果 \(i,j\) 互质,就是说质数 \(p\) 不可能同时出现于 \(i,j\),很明显,\(d(ij)=\sum_{x\mid i}\sum_{y\mid j}[\gcd(x,y)==1]\)\(xy\) 就是 \(ij\) 因数之一)。

如果 \(i,j\) 不互质呢?\(d(ij)=\sum_{x\mid i}\sum_{y\mid j}[\gcd(x,y)==1]\) 好像就不成立了,像 \(x=2,y=1\)\(x=1,y=2\) 好像重复了(这里 \(i=4,j=8\))。对于这个问题,其实 \(x=1,y=2\)\(x=2,y=1\) 是不等价的,因为我们总是先取 \(i\),如果取了 \(j\) 的话,\(i\) 肯定已经取完了,所以 \(x=1,y=2\) 它们代表的 \(ij\) 因子其实是 \(4\times 2=8\)

但是还有一个问题,如何保证 \(x,y\) 互质时,它们所代表的数一定是 \(ij\) 的因数呢?换言之,我们怎么才能证明 \(ij\) 的因数一定能表示成互质的 \(x,y\) 呢?这个问题很简单,通过上面的例子能得到,如果质因数 \(p\) 已经在 \(i\) 中取完了,\(p\)\(x\) 中就只会表示为 \(1\)。所以不可能在 \(x,y\) 中同时找到 \(p\),所以 \(x,y\) 必须互质。

\(d(ij)=\sum_{x\mid i}\sum_{y\mid j}[\gcd(x,y)==1]\),关于这个性质的问题已经解决好了,接下来就是简单的推狮子🦁了:

\[\begin{aligned}\sum_{i=1}^{n}\sum_{j=1}^{m}d(ij)&=\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_{k\mid\gcd(x,y)}\mu(k)\end{aligned}\]

将关于 \(x,y\) 的所有和式提前:

\[\begin{aligned}\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{x\mid i}\sum_{y\mid j}\sum_{k\mid\gcd(x,y)}\mu(k)&=\sum_{x=1}^{n}\sum_{y=1}^{m}\sum_{k\mid\gcd(x,y)}\mu(k)\sum_{i=1}^{\lfloor\frac{n}{x}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{y}\rfloor}1\\ &=\sum_{x=1}^{n}\sum_{y=1}^{m}\sum_{k\mid\gcd(x,y)}\mu(k)\left\lfloor\frac{n}{x}\right\rfloor\left\lfloor\frac{m}{y}\right\rfloor\end{aligned}\]

再将 \(\mu\) 提前:

\[\begin{aligned}\sum_{x=1}^{n}\sum_{y=1}^{m}\sum_{k\mid\gcd(x,y)}\mu(k)\left\lfloor\frac{n}{x}\right\rfloor\left\lfloor\frac{m}{y}\right\rfloor &= \sum_{k=1}^{n}\mu(k)\sum_{x=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{y=1}^{\lfloor\frac{m}{k}\rfloor}\left\lfloor\frac{n}{xk}\right\rfloor\left\lfloor\frac{m}{yk}\right\rfloor\\ &=\sum_{k=1}^{n}\mu(k)\sum_{x=1}^{\lfloor\frac{n}{k}\rfloor}\left\lfloor\frac{n}{xk}\right\rfloor\sum_{y=1}^{\lfloor\frac{m}{k}\rfloor}\left\lfloor\frac{m}{yk}\right\rfloor\end{aligned}\]

到这一步,是的,先预处理整除分块 \(\sum_{i=1}^{x}\left\lfloor\frac{x}{i}\right\rfloor\),再继续莫比乌斯的老套路。

代码:

inline void prework()
{
	miu[1] = 1;
	for (int i = 2; i <= N - 10; i++)
	{
		if(!vis[i]) {pri[++cnt] = i, miu[i] = -1;}
		for (int j = 1; j <= cnt && pri[j] * i <= N - 10; j++)
		{
			vis[pri[j] * i] = 1;
			if (i % pri[j] == 0)
			{
				miu[i * pri[j]] = 0;
				break;
			}
			else
				miu[i * pri[j]] = -miu[i];
		}
	}
	for (int i = 1; i <= N - 10; i++)
		sum[i] = miu[i] + sum[i - 1];
	for (int n = 1; n <= N - 10; n++)
		for (register int l = 1, r; l <= n; l = r + 1)
		{
			r = n / (n / l);
			Ans[n] += (r - l + 1) * (n / l);
		}
}

int main()
{
	prework();
	for (read(t); t--; )
	{
		ll ans = 0LL;
		read(n);read(m);
		if(n > m)
		{
			ll c = n; n = m; m = c;
		}
		for (register int l = 1, r; l <= n; l = r + 1)
		{
			r = min (n / (n / l), m / (m / l));
			ans += (sum[r] - sum[l - 1]) * Ans[n / l] * Ans[m / l];
		}
		printf("%lld\n", ans);
	}
	return 0;
}
posted @ 2020-11-20 15:11  Jayun  阅读(93)  评论(1编辑  收藏  举报