题目大意:

找第k个非平方数,平方数定义为一个数存在一个因子可以用某个数的平方来表示

 

这里首先需要考虑到二分才可以接下来做

二分去查找[1 , x]区间内非平方数的个数,后面就是简单的莫比乌斯反演了

容斥原理的思想,首先考虑所有数都属于非平方数 那么就是x

然后对于每一个平方数都要减去,但是这里应该只考虑质数的平方数就可以了

那么就扩展为x - x/(2^2) - x/(3^2) - x/(k^2)....

然后因为中间存在重复减的那么要加回来

-> x - x/(2^2) - x/(3^3) - x/(k^k)+ x/(2^2*3^2)+x/(2^2*4^2)....

后面3个质因数的平方组合就是 *(-1) 了

以此类推,那么k个数组成的质因数平方就是 *(-1)^k

其实这就是一个莫比乌斯函数了

这是积性函数,用线性筛法跑一遍就行了,因为都是平方的,所以筛到不超过1000000就足够了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define N 100000
 5 int mu[N+5] , prime[N+5] , tot;
 6 bool check[N+5];
 7 void get_mu()
 8 {
 9     tot = 0;
10     for(int i=2 ; i<=N ; i++){
11         if(!check[i]){
12             prime[tot++] = i;
13             mu[i] = -1;
14         }
15         for(int j=0 ; j<tot ; j++){
16             if((ll)i*prime[j]>N) break;
17             check[i*prime[j]] = true;
18             if(i%prime[j]==0){
19                 mu[i*prime[j]] = 0;
20                 break;
21             }else mu[i*prime[j]] = -mu[i];
22         }
23     }
24 }
25 
26 bool ok(int m , int n)
27 {
28     int mx = (int)(sqrt(m+0.5)) , ret = m;
29     for(int j=2 ; j<=mx ; j++){
30         ret += m/(j*j)*mu[j];
31     }
32     return ret>=n;
33 }
34 
35 int solve(int n)
36 {
37     int l=0 , r=2*(1e9) , ans=0;
38     while(l<=r){
39         int m = ((ll)l+r)/2;
40        // cout<<m<<endl;
41         if(ok(m , n)){
42             r=m-1;
43             ans=m;
44         }
45         else{
46             l = m+1;
47         }
48     }
49     return ans;
50 }
51 
52 int main()
53 {
54   //  freopen("in.txt" , "r" , stdin);
55     get_mu();
56     int T;
57     scanf("%d" , &T);
58     while(T--){
59         int n;
60         scanf("%d" , &n);
61         printf("%d\n" , solve(n));
62     }
63     return 0;
64 }

 

 posted on 2015-09-06 00:19  Love风吟  阅读(283)  评论(0编辑  收藏  举报