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;
}