luogu P4318 完全平方数

luogu P4318 完全平方数

今天膜你赛的时候我想推一个 \(\sum\limits_{i=1}^n \mu^2(i)\),结果太弱智了没推出来,然后就来看了这道题。

首先考虑二分答案。现在问题就转化为如何求上述式子。

对每个质因子的平方进行容斥,发现对于每个数容斥系数恰好是 \(u(i)\)。所以原式即为 \(\sum\limits_{i=1}^{\lfloor\sqrt n \rfloor}\mu(i)\lfloor \frac{n}{i^2}\rfloor\)。时间复杂度 \(O(\sqrt n+TlogK)\)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define int long long

using namespace std;

const int N = 100000;
int k, a[N + 9], p[N], cnt, u[N + 9];

void prework()
{
	u[1] = 1;
	for (int i = 2; i <= N; i++)
	{
		if (!a[i])
			a[i] = i, p[++cnt] = i, u[i] = -1;
		for (int j = 1; j <= cnt; j++)
		{
			if (p[j] > a[i] || p[j] > N / i)
				break;
			a[p[j] * i] = p[j];
			if (i % p[j])
				u[p[j] * i] = u[p[j]] * u[i];
		}
	}
}

void init()
{
	scanf("%lld", &k);
}

int check(int n)
{
	int res = 0;
	for (int i = 1; i * i <= n; i++)
		res += u[i] * (n / (i * i));
	return res;
}

void work()
{
	int l = 1, r = 2e10, mid;
	while (l <= r)
	{
		mid = l + r >> 1;
		if (check(mid) < k)
			l = mid + 1;
		else
			r = mid - 1;
	}
	printf("%lld\n", l);
}

signed main()
{
	prework();
	int T;
	scanf("%lld", &T);
	while (T--)
	init(),
	work();
	return 0;
}

posted @ 2020-09-19 22:21  With_penguin  阅读(93)  评论(0编辑  收藏  举报