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

      

  • 相关阅读:
    【BZOJ 2124】【CodeVS 1283】等差子序列
    【BZOJ 1036】【ZJOI 2008】树的统计Count
    【BZOJ 1901】【ZJU 2112】Dynamic Rankings
    【BZOJ 3924】【ZJOI 2015】幻想乡战略游戏
    【BZOJ 4103】【THUSC 2015】异或运算
    【BZOJ 4513】【SDOI 2016】储能表
    【HDU 3622】Bomb Game
    【BZOJ 3166】【HEOI 2013】Alo
    【BZOJ 3530】【SDOI 2014】数数
    【BZOJ 4567】【SCOI 2016】背单词
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4480844.html
Copyright © 2020-2023  润新知