UESTC618:无完全平方因子数
UESTC618:无完全平方因子数
题意:
给定一个\(n\),求区间\([1,n]\)中的无平方因子数的个数。
比如说20就是一个有平方因子数,因为\(20=2^2\times 5\)。
思路:
对于一个数,根据算术基本定理,一定可以拆成若干个整数相乘的形式,记为\(x=p_1^{c_1},...,p_n^{c_n}\)的形式。
-
那么当一个数字的\(c_i\geq 2\)的时候,这个数字一定是有平方因子数。
-
如果所有的\(c_i\)都是\(1\),那么这个数字一定是无平方因子数。
那么答案就是莫比乌斯函数的平方和。
\[S(n) = \sum_{i=1}^n \mu^2(i)
\]
虽然这里看起来很明显的需要杜教筛,但是我找不出合适的\(g\)函数来卷,可能有方法,但我不知道。
考虑一个数\(p\),那么\(p^2\)的倍数都有平方因子,这样的数字有\(\frac{n}{p^2}\)个,应该从答案中去除。
但是对于两个素数\(p_1,p_2\)而言,\(p_1^2p_2^2\)的倍数会被去掉两次,所以应该加回来,这里显然是容斥原理,而且莫比乌斯函数恰好为系数。
假设说\(d\)是几个不同的素数的乘积,那么他们对答案的贡献一定是:
\[\mu(d)\frac{n}{d^2}
\]
所以说答案改写为了:
\[\sum_{i=1}^n\mu^2=\sum_{d=1}^{\sqrt{n}}\mu(d)\frac{n}{d^2}
\]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6;
bool vis[maxn+10];
int primes[maxn+10], cnt, mu[maxn+10];
void init(int n)
{
mu[1] = 1;
for(int i = 2; i <= n; i++)
{
if(!vis[i])
{
primes[++cnt] = i;
mu[i] = -1;
}
for(int j = 1; primes[j] <= n/i; j++)
{
vis[primes[j]*i] = 1;
if(i % primes[j] == 0) break;
else mu[i*primes[j]] = -mu[i];
}
}
}
ll n;
void solve()
{
cin >> n; ll res = 0;
for(ll i = 1; i <= n/i; i++)
res += 1ll*mu[i]*n/(i*i);
cout << res << endl;
}
int main()
{
init(maxn);
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}