题目大意:
找第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 }
我还在坚持,我还未达到我所想,梦~~一直在