Square-free integers SPOJ - SQFREE

原题链接
考察:容斥原理 or 莫比乌斯反演
思路:
  枚举平方数:
\(2^2,3^2,4^2,5^2,6^2,...,1e^{7^2}\)
  对于\(2^2\)需要减去,\(3^2\)需要减去,\(4^2\)不需要计入,\(6^2\)需要减去...如果忽视指数,这就对应了莫比乌斯函数,我们预处理1e7以内的质数,然后利用\(mob[i]\times\frac{n}{i\times i}\)即可.注意到这里可以分块,但是求的右端点是需要sqrt的,因为我们是在平方数的下标下求和.

Code

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 1e7+10;
int prime[N],cnt,mob[N],sum[N];
bool st[N];
LL n;
void GetPrime(int n) 
{
	mob[1] = 1;
	for(int i=2;i<=n;i++)
	{
		if(!st[i]) prime[++cnt] = i,mob[i] = -1;
		for(int j=1;prime[j]<=n/i;j++)
		{
			st[i*prime[j]] = 1;
			if(i%prime[j]==0) break;
			mob[i*prime[j]] = (-1)*mob[i];
		}
	}
	for(int i=1;i<=n;i++)
	  sum[i] = sum[i-1]+mob[i];
}
int main()
{
	int T;
	scanf("%d",&T);
	GetPrime(N-1);
	while(T--)
	{
		scanf("%lld",&n);
		LL ans = 0;
		for(LL i=1,r;i<=n/i;i=r+1)
		{
			r = sqrt(n/(n/(i*i)));
			ans+=(LL)(sum[r]-sum[i-1])*(n/(i*i));
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2021-06-17 21:02  acmloser  阅读(64)  评论(0编辑  收藏  举报