数学(莫比乌斯函数):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
1
13
100
1234567
Sample Output
1
19
163
2030745
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 }
尽最大的努力,做最好的自己!