bzoj 2440 二分+莫比乌斯函数和容斥原理

题意:输出第k小的无平方因子的数

无平方因子数:分解质因子后,所有质因数的次数都为1

第k小,考虑二分答案

我们发现,如果直接去找[1,x]的无平方因子数的个数,我们发现,可能对于多个x,[1,x]内的无平方因子数是一样的,所以我们不能找到确切的答案

既然不能直接求,考虑补集思想,我们只要找出[1,x]内有多少个有平方因子的数,再用x减去即可,并且我们可以找到确切的答案

根据不重不漏原则,我们考虑容斥原理

[1,x]内有平方因子的数=x-有一个质因数的次数为2的数的倍数的数的数量+有两个质因数次数为2的数的倍数的数的数量-...(x可以看做1的倍数的个数)

然后根据莫比乌斯函数的定义,对于每个乘积a,前面的符号刚好是μ(a),而x内有floor(x/a*a) 个 a*a的倍数的数

所以[1,x]内,有 sigma(μ(i)*floor(x/a*a))  ( 1<=i<=sqrt(x) ) 个无平方因子的数

const
   inf= 1644934500;
var
        t,l,mid,x,ans,r :longint;
        vis             :array[0..41010] of boolean;
        pri,miu         :array[0..41010] of longint;
procedure pre_do;
var
        i,j:longint;
        tt:longint;
begin
   miu[1]:=1;
   for i:=2 to trunc(sqrt(inf)) do
   begin
      if not vis[i] then
      begin
         inc(t);
         pri[t]:=i;
         miu[i]:=-1;
      end;
      for j:=1 to t do
        if (i*pri[j]>trunc(sqrt(inf))) then break else
        begin
           vis[i*pri[j]]:=true;
           if (i mod pri[j]<>0) then miu[i*pri[j]]:=-miu[i] else
           begin
              miu[i*pri[j]]:=0;
              break;
           end;
        end;
   end;
end;

function solve(x:longint):longint;
var
        ans:longint;
        i:longint;
begin
   ans:=0;
   for i:=1 to trunc(sqrt(x)) do
      inc(ans,miu[i]*(x div (i*i)));
   exit(ans);
end;

begin
   pre_do;
   read(t);
   while (t>0) do
   begin
      dec(t);
      read(x);
      l:=1;r:=inf;
      while (l<=r) do
      begin
         mid:=(int64(l)+int64(r)) div 2;
         if solve(mid)>=x then
         begin
            ans:=mid;r:=mid-1;
         end else l:=mid+1;
      end;
      writeln(ans);
   end;
end.

——by Eirlys

bzoj 2440 二分+莫比乌斯函数和容斥原理_第1张图片

你可能感兴趣的:(二分,bzoj,莫比乌斯反演,容斥原理)