bzoj 2440 完全平方数

这是一道论文题。

题意:选出第k个无平方因子的数。

 

思路:二分答案。

某一个区间的无平方因子的数的个数怎么求呢? 可以筛。

这里可以莫比乌斯。

首先什么是莫比乌斯函数呢?

 

 

回到本题:

他是一个莫比乌斯函数的应用。

对于1~ mid 中,不含平方因子的个数为:

n - sum(i^2)   其中 i 为素数。

 

含不含平方因子:就是将 N 质因数分解,只有u(n) != 0的值才是不含质因数因子的。但是开不来10^9的数组,来遍历u(n),用素数优化。

例如: 4,9,4n,9n,这些数得删掉,4的倍数的个数 为 n/4   n/9,

所谓平方因子也是 一些素数的平方得到的。

 

那么这里就有一个容斥定理,n - 每个质数的平方因子的数的倍数,(这里不用算素数,因为有莫比乌斯函数做系数)+每两个质数的乘积的平方因子的数的倍数-每三个... ...

例如:删掉了4的倍数,9的倍数,那么36就被删了两次,(容斥定理)

#include <bits/stdc++.h>

using namespace std;

const int n = 1e+5;

typedef long long ll;

int mu[n];

void getMu() {
    for(int i=1;i<=n;i++) {
        int target = i == 1? 1: 0;
        int delta = target - mu[i];
        mu[i] = delta;

        for(int j=i+i;j<=n;j+=i)
            mu[j] +=delta;

    }
}

ll k;
ll calc(ll mid) {
    ll sq = sqrt(mid);
    ll ans = 0;
    for(ll i=1;i<=sq;++i) {
        ans+=mu[i]*(mid/(i*i));
    }
    return ans;
}

int main(int argc, char const *argv[])
{
    getMu();
    ll t;
    scanf("%I64d",&t);
    for(ll z=0;z<t;++z) {
        scanf("%I64d",&k);

        ll l = 0,r = k*2;

        while(l<r) {
            ll mid = (l+r)/2;
            if(calc(mid)>=k)
                r = mid;
            else l = mid + 1;
        }
        cout<<l<<endl;
    }
    return 0;
}
View Code

 

posted @ 2017-07-28 10:17  小草的大树梦  阅读(215)  评论(0编辑  收藏  举报