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

来源:互联网 发布:百度云搜索cms程序 编辑:程序博客网 时间:2024/05/27 21:49

题意:输出第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


0 0
原创粉丝点击