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

    xiaoxiao2021-03-26  30

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

    转载请注明原文地址: https://ju.6miu.com/read-661048.html

    最新回复(0)