BZOJ-2440 完全平方数 (莫比乌斯函数的应用)

  • 题意: 输入k,输出第K个因子中不含完全平方数的值。k < 1e9
  • 题解:
    容斥思想:先减4的倍数的个数,再减去9的倍数的个数...由于多减了,还要加上36的倍数的个数...每个值加还是减根据莫比乌斯函数mu[i]判断。
    二分:范围很大,就可以想到二分,二分答案求1~x之间有多少无平方因子数。
    对0~sqrt(n)以内所有的质数, x以内无平方因子数 = 0个质数乘积的平方的倍数的数的数量 - 每个质数的平方的倍数的数量 + 每2个质数乘积的平方的倍数的数量....
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N = 4e5 + 5;

int pri[N], cnt;
int mu[N];
int vis[N];
ll T, k;

void prime(){
    mu[1] = 1;
    for(int i = 2; i <= 4e5; ++ i){
        if(!vis[i]){
            pri[++ cnt] = i;
            mu[i] = -1;
        }
        for(int j = 1; j <= cnt && pri[j] * i <= 4e5; ++ j){
            vis[pri[j] * i] = 1;
            if(i % pri[j] == 0){
                mu[pri[j] * i] = 0;
                break;
            }
            mu[pri[j] * i] = -mu[i];
        }
    }
}

bool check(ll x){
    ll div = sqrt(x);
    ll sum = 0;
    for(ll i = 1; i <= div; ++ i){
        if(mu[i]) sum += mu[i] * x / (i * i);	
    }
    return sum >= k;
}


int main()
{
    prime();
    scanf("%lld",&T);
    while(T --){
        scanf("%lld", &k);
        ll l = 1, r = 2 * k + 1;
        while(l < r){
            ll mid = (l + r) >> 1;
            if(check(mid)) r = mid;
            else l = mid + 1;
        }
        printf("%lld\n",l);
    }
    return 0;
}

posted @ 2020-04-03 14:10  A_sc  阅读(149)  评论(0编辑  收藏  举报