【Luogu P2257】 YY的GCD

题目链接:

题目

博客园

题目大意:

快速求:

\[\sum_{p\in Prime}\sum_{i=1}^{n}\sum_{j=1}^{m}\left[\operatorname{gcd}(i,j)==p\right] \]

正文:

按照莫比乌斯反演的常规套路,将式子化简成我们能接受的时限:

\[\begin{aligned}\sum_{p\in Prime}\sum_{i=1}^{n}\sum_{j=1}^{m}\left[\operatorname{gcd}(i,j)==p\right] &=\sum_{p\in Prime}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}\left[\operatorname{gcd}(i,j)==1\right]\\&=\sum_{p\in Prime}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}\sum_{d|\operatorname{gcd}(i,j)}\mu(d)\\&=\sum_{p\in Prime} \sum_{d=1}\mu(d)\sum_{d|i}^{\lfloor\frac{n}{p}\rfloor}\sum_{k|j}^{\lfloor\frac{m}{p}\rfloor}1\\&=\sum_{p\in Prime}\sum_{d=1}\mu(d)\left\lfloor\frac{n}{pd}\right\rfloor\left\lfloor\frac{m}{pd}\right\rfloor\end{aligned} \]

\(k=pd\) 枚举 \(k\)

\[\begin{aligned}\sum_{p\in Prime}\sum_{d=1}\mu(d)\left\lfloor\frac{n}{pd}\right\rfloor\left\lfloor\frac{m}{pd}\right\rfloor&=\sum_{k=1}\left\lfloor\frac{n}{k}\right\rfloor\left\lfloor\frac{m}{k}\right\rfloor\sum_{p|k,p\in Prime}\mu(\frac{k}{p})\end{aligned} \]

预处理 \(\mu(\frac{k}{p})\),就能 \(O(t\sqrt{n})\)

代码:

稍微卡卡常就能过了。

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 <= cnt; i++)
		for (int j = 1; j * pri[i] <= N - 10; j++)
			sum[j * pri[i]] += miu[j];
	for (int i = 1; i <= N - 10; i++)
		sum[i] += sum[i - 1];
}

int main()
{
	prework();
	for (read(t); t--; )
	{
		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]) * (n / l) * (m / l);
		}
		print(ans);
	}
	return 0;
}
posted @ 2020-09-03 20:18  Jayun  阅读(118)  评论(0编辑  收藏  举报