[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.

 

 

 

 

  

 

posted @ 2015-05-06 08:29  mjy0724  阅读(272)  评论(0编辑  收藏  举报