数学(莫比乌斯函数):BZOJ 2440 完全平方数

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

  通过容斥原理可以发现莫比乌斯函数起了作用。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=50010;
 6 int prime[maxn],cnt;
 7 int mu[maxn];
 8 bool check[maxn];
 9 
10 void Prepare(){
11     mu[1]=1;
12     for(int i=2;i<=50000;i++){
13         if(!check[i]){
14             prime[++cnt]=i;
15             mu[i]=-1;
16         }
17         for(int j=1;j<=cnt;j++){
18             if(prime[j]*i>50000)break;
19             check[prime[j]*i]=true;
20             if(i%prime[j]==0){
21                 mu[prime[j]*i]=0;
22                 break;
23             }
24             mu[prime[j]*i]=mu[i]*-1;
25         }
26     }
27 }
28 
29 int Solve(int k){
30     int l=k,r=1644934081;
31     while(l<=r){
32         int mid=(1ll*l+1ll*r)>>1;
33         long long tot=0;
34         for(int i=1;i*i<=mid;i++)
35             tot+=mid/(i*i)*mu[i];
36         if(tot>=k)r=mid-1;
37         else l=mid+1;    
38     }
39     return l;
40 }
41 int T,k;
42 int main(){
43     //freopen("","",stdin);
44     //freopen("","",stdout);
45     Prepare();
46     scanf("%d",&T);
47     while(T--){
48         scanf("%d",&k);
49         printf("%d\n",Solve(k));
50     }
51     return 0;
52 }

 

posted @ 2016-07-25 16:28  TenderRun  阅读(210)  评论(0编辑  收藏  举报