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

posted @ 2020-03-16 17:04  zhaoxiaoyun  阅读(234)  评论(0编辑  收藏  举报