【BZOJ2440】完全平方数(中山市选2011)-二分答案+莫比乌斯函数应用

测试地址:完全平方数
题目大意:求第 K 小的不是任何完全平方数倍数的正整数。
做法:这一题需要用到二分答案+莫比乌斯函数。
一般我们看到求第K小的啥啥啥一般就会先想到二分答案了,那么转化成判定性问题:在区间 [1,x] 中有多少个不是任何完全平方数倍数的整数?在区间 [1,x] 内的完全平方数有 22,32,...,x2 ,要把是这些东西的倍数的数去掉,我们可以将每个完全平方数的平方根分解质因子,可以分成若干种质因子,那么根据容斥原理,答案就是:总数-平方根分解为 1 个互异质因子的平方数(如22,32)的倍数个数+平方根分解为 2 个互异质因子的平方数(如62,102)的倍数个数-…+ (1)k× 平方根分解为 k 个互异质因子的平方数的倍数个数。观察这一个定义,发现平方数i2倍数个数前面的符号就是莫比乌斯函数 μ(i) ,又因为 [1,x] i2 的倍数有 xi2 个,所以答案就可以表示为 xi=1μ(i)xi2 ,这样我们只需线性筛预处理出一定范围内的莫比乌斯函数值就可以了。总的时间复杂度约为 O(KlogK) ,可以通过此题。
以下是本人代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
int T;
ll k,mu[50010];
bool prime[50010];

void calc_mu()
{
  ll n=2*(ll)1e9,sq=(ll)sqrt(n)+1;
  for(ll i=1;i*i<=n;i++) mu[i]=1;
  for(ll i=2;i*i<=n;i++)
  {
    if (!prime[i])
    {
      for(ll j=1;i*j<=sq;j++)
      {
        prime[i*j]=1;
        if (!(j%i))
        {
          mu[i*j]=0;
          continue;
        }
        mu[i*j]*=-1;
      }
    }
  }
}

ll solve(ll x)
{
  ll s=x;
  for(ll i=2;i*i<=x;i++)
    s+=mu[i]*(x/(i*i));
  return s;
}

int main()
{
  scanf("%d",&T);
  calc_mu();
  while(T--)
  {
    scanf("%lld",&k);
    ll l=1,r=2*(ll)1e9;
    while(l!=r)
    {
      ll mid=(l+r)>>1,s;
      s=solve(mid);
      if (s>=k) r=mid;
      else l=mid+1;
    }
    printf("%lld\n",l);
  }

  return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值