bzoj 2440 (莫比乌斯函数)

来源:互联网 发布:linux 获取文件夹大小 编辑:程序博客网 时间:2024/06/11 21:45

bzoj 2440 完全平方数

题意:找出第k个不是完全平方数的正整数倍的数。

例如 4  9  16  25 36什么的
通过容斥原理,我们减去所有完全数  4有n/4个,但是先36这种会被重复减去,
所有我们还需要加上类似36的数,然后你会发现这些数前面的符号和他们开根号的
莫比乌斯函数一样
数据很大有1e9,如果先进行预处理再从头到尾找感觉不现实,考虑使用二分,枚举mid,
然后每次查找1到mid中不是完全平方数的正整数倍的数的个数


Orz:机制的二分使用


#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <queue>#include <vector>#include <algorithm>#include <functional>typedef long long ll;using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 1e5;int tot;int is_prime[maxn];int mu[maxn];int prime[maxn];void Moblus(){    tot = 0;    mu[1] = 1;    for(int i = 2; i < maxn; i++)    {        if(!is_prime[i])        {            prime[tot++] = i;            mu[i] = -1;        }        for(int j = 0; j < tot && i*prime[j] < maxn; j++)        {            is_prime[i*prime[j]] = 1;            if(i % prime[j])            {                mu[i*prime[j]] = -mu[i];            }            else            {                mu[i*prime[j]] = 0;                break;            }        }    }    }ll get_(ll mid){    ll num = 0;    for(int i = 1; i*i <= mid; i++)    {        num += (ll)mu[i]*(mid/(i*i));    }    return num;}int main(){    int T;    Moblus();    scanf("%d",&T);    while(T--)    {        ll k;        scanf("%lld",&k);        ll l = 1;        ll r = 2*k+1;        while(l <= r)        {            ll mid = (l+r)>>1;            ll num = get_(mid);            if(num < k)                l = mid + 1;            else                r = mid - 1;        }        printf("%lld\n",l);    }}




0 0
原创粉丝点击