zoukankan      html  css  js  c++  java
  • BZOJ2440完全平方数(莫比乌斯反演)

    Description

    小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些
    数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而
    这丝毫不影响他对其他数的热爱。 
    这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一
    个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了
    小X。小X很开心地收下了。 
    然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?

    Input

    包含多组测试数据。文件第一行有一个整数 T,表示测试
    数据的组数。 
    第2 至第T+1 行每行有一个整数Ki,描述一组数据,含义如题目中所描述。 

    Output

    含T 行,分别对每组数据作出回答。第 i 行输出相应的
    第Ki 个不是完全平方数的正整数倍的数。

    Sample Input

    4
    1
    13
    100
    1234567

    Sample Output

    1
    19
    163
    2030745

    HINT

    对于 100%的数据有 1 ≤ Ki ≤ 10^9

    ,    T ≤ 50

    题解:

    题目大意:求第k个无平方因子数是多少(无视原题干,1也是完全平方数那岂不是一个数也送不出去了?

    无平方因子数(square-free number),即质因数分解之后所有质因数的次数都为1的数

    首先二分答案 问题转化为求x以内有多少个无平方因子数

    根据容斥原理可知 对于√x以内的所有质数 x以内的无平方因子数=无需是任何质数的倍数的数的数量(即x)-是至少一个质数平方倍数的数的数量+是至少两个质数平方倍数的数的数量-是至少三个质数平方倍数的数的数量...

    我们回去考虑莫比乌斯函数,我们发现每一个质数乘积的符号与莫比乌斯函数的符号恰好吻合!

    于是我们枚举每一个数,如果这个数是奇数个不同质数的乘积,那么mu为负,偶数个则mu为正,否则mu为零

    故答案即Σx/(i*i)*mu[i]

     1 /**************************************************************
     2     Problem: 2440
     3     User: SongHL
     4     Language: C++
     5     Result: Compile_Error
     6 ****************************************************************/
     7  
     8  
     9 #include<bits/stdc++.h>
    10 using namespace std;
    11 typedef long long ll;
    12 const int maxn=5e4+10;
    13 ll Prime[maxn],mob[maxn],vis[maxn],cnt;
    14 int T,K;
    15  
    16 void Mobius()
    17 {
    18     memset(Prime,0,sizeof Prime);
    19     memset(mob,0,sizeof mob);
    20     memset(vis,0,sizeof vis);
    21     mob[1]=1; cnt=0;
    22     for(ll i=2;i<maxn;++i)
    23     {
    24         if(!vis[i]) Prime[cnt++]=i,mob[i]=-1;
    25         for(ll j=0;j<cnt&&i*Prime[j]<maxn;++j)
    26         {
    27             vis[i*Prime[j]]=1;
    28             if(i%Prime[j]) mob[i*Prime[j]]=-mob[i];
    29             else { mob[i*Prime[j]]=0; break;}
    30         }
    31     }
    32 }
    33  
    34 int work(int x)
    35 {
    36     int ans=0;
    37     for(int i=1;i*i<=x;++i) ans+=x/(i*i) * mob[i];
    38     return ans;
    39 }
    40  
    41 int Judge()
    42 {
    43     int l=1,r=K<<1,mid;
    44     while(l+1<r)
    45     {
    46         mid=(l>>1)+(r>>1) +(l&r&1);
    47         if(work(mid)>=K) r=mid;
    48         else l=mid;
    49     }
    50     if(work(l)>=K) return l;
    51     return r;
    52 }
    53  
    54 int main()
    55 {
    56     scanf("%d",&T);
    57     Mobius();
    58     while(T--) { scanf("%d",&K); printf("%d
    ",Judge()); }
    59     return 0;
    60 }
    View Code

      

  • 相关阅读:
    设计模式--单例模式Singleton
    CSS选择器
    操作数据表
    HTML
    Shell学习
    LINUX常用命令
    多线程-互斥变量
    多线程-临界区
    每天一个linux命令:file(11)
    JavaScript设计模式小抄集(持续更新)
  • 原文地址:https://www.cnblogs.com/csushl/p/9807997.html
Copyright © 2011-2022 走看看