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\n",Judge()); }
59     return 0;
60 }
View Code

 

  

posted @ 2018-10-18 00:00  StarHai  阅读(442)  评论(0编辑  收藏  举报