zoukankan      html  css  js  c++  java
  • UESTC618:无完全平方因子数

    UESTC618:无完全平方因子数

    题意:

    给定一个(n),求区间([1,n])中的无平方因子数的个数。

    比如说20就是一个有平方因子数,因为(20=2^2 imes 5)

    思路:

    对于一个数,根据算术基本定理,一定可以拆成若干个整数相乘的形式,记为(x=p_1^{c_1},...,p_n^{c_n})的形式。

    • 那么当一个数字的(c_igeq 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}^nmu^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;
    }
    
    
  • 相关阅读:
    [转]手工实现RTTI
    小楫轻舟
    百年孤独
    The power of now
    [转帖]Android平台下OpenGL初步
    设计模式六大原则(5):迪米特法则
    设计模式六大原则(4):接口隔离原则
    设计模式六大原则(3):依赖倒置原则
    设计模式六大原则(1):单一职责原则
    设计模式六大原则(2):里氏替换原则
  • 原文地址:https://www.cnblogs.com/zxytxdy/p/12505034.html
Copyright © 2011-2022 走看看