[BZOJ2440]完全平方数解题报告|莫比乌斯函数的应用
完全平方数
小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而这丝毫不影响他对其他数的热爱。
这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了小X。小X很开心地收下了。
然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?
还记得第一次接触这道题是一年前吧..那时候参加了一场某OJ的比赛
然后并不会做..在discuss里面发现是“BZOJ2440原题”
然后看到了一个叫做莫比乌斯函数的东西...很努力地看但是仍然没看懂...
也奇怪..现在就能看懂了呢...
莫比乌斯函数:
μ(1)=1;
对于每个质因子的次数都为1的数n,假设其能拆分出k个质因子,μ(n)=(-1)^k
其他情况下μ(n)=0
构造方法:
首先容易证明莫比乌斯函数是积性函数
然后用线筛
procedure build; var m:int64; i,j:longint; begin fillchar(vis,sizeof(vis),true); prime[0]:=0; m:=trunc(sqrt(INF));mu[1]:=1; for i:=2 to m do begin if vis[i] then begin inc(prime[0]); prime[prime[0]]:=i; mu[i]:=-1; end; for j:=1 to prime[0] do begin if i*prime[j]>m then break; vis[i*prime[j]]:=false; if i mod prime[j]=0 then begin mu[prime[j]*i]:=0; break; end; mu[prime[j]*i]:=-mu[i]; end; end; end;
对于这道题,很容易想到二分答案+容斥
然后发现由偶数个次数为一的质数乘起来的完全平方因子,对答案的贡献是正的,奇数个是负的
这个就可以用莫比乌斯函数来替代
1 program bzoj2440; 2 const INF = 1644934500;maxn = 41000; 3 var test,L,R,ans,k,mid:int64; 4 tt:longint; 5 prime,mu:array[-1..maxn]of int64; 6 vis:array[-1..maxn]of boolean; 7 8 procedure build; 9 var m:int64; 10 i,j:longint; 11 begin 12 fillchar(vis,sizeof(vis),true); 13 prime[0]:=0; 14 m:=trunc(sqrt(INF));mu[1]:=1; 15 for i:=2 to m do 16 begin 17 if vis[i] then 18 begin 19 inc(prime[0]); 20 prime[prime[0]]:=i; 21 mu[i]:=-1; 22 end; 23 for j:=1 to prime[0] do 24 begin 25 if i*prime[j]>m then break; 26 vis[i*prime[j]]:=false; 27 if i mod prime[j]=0 then 28 begin 29 mu[prime[j]*i]:=0; 30 break; 31 end; 32 mu[prime[j]*i]:=-mu[i]; 33 end; 34 end; 35 end; 36 37 function solve(x:int64):int64; 38 var sum:int64; 39 i:longint; 40 begin 41 sum:=0; 42 for i:=1 to trunc(sqrt(x)) do 43 inc(sum,(x div (int64(i)*i))*mu[i]); 44 45 exit(sum); 46 end; 47 48 begin 49 assign(input,'bzoj2440.in');reset(input); 50 readln(test); 51 build; 52 for tt:=1 to test do 53 begin 54 readln(k); 55 L:=1;R:=INF;ans:=-1; 56 while L<=R do 57 begin 58 mid:=(L+R) >> 1; 59 if solve(mid)>=k then 60 begin 61 ans:=mid;R:=mid-1; 62 end else L:=mid+1; 63 end; 64 writeln(ans); 65 end; 66 end.