bzoj2440 完全平方数 莫比乌斯值+容斥+二分
莫比乌斯值+容斥+二分 /** 题目:bzoj2440 完全平方数 链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2440 题意:求第k个小x数。小x数是指不存在某个素因子次数>=2。1也是小x数。 思路:二分x,求[1,x]有多少个小x数。如果一个数是某个素数的平方的倍数,那么不是小x数。 所以要减去。2^2的倍数, 3^2的倍数, 5^2的倍数. 由于减去2的平方的倍数和3的平方的倍数把6的平方的倍数多减去了一次。所以要加回去。 ans = sigma[1,sqrt(x)] mu[i]*x/i/i ; */ #include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <iostream> #include <vector> #include <map> using namespace std; typedef long long LL; #define ms(x,y) memset(x,y,sizeof x) typedef pair<int, int> P; const LL INF = 1e10; const int mod = 1e9 + 7; const int maxn = 1e5 + 100; int prime[maxn], tot, not_prime[maxn]; int mu[maxn]; map<LL,LL> mp; void get() { mu[1] = 1; tot = 0; for(int i = 2; i < maxn; i++){ if(!not_prime[i]){ prime[++tot] = i; mu[i] = -1; } for(int j = 1; prime[j]*i<maxn; j++){ not_prime[prime[j]*i] = 1; if(i%prime[j]==0){ mu[prime[j]*i] = 0; break; } mu[prime[j]*i] = -mu[i]; } } } LL solve(LL x) { LL ans = 0; for(LL i = 1; i*i<=x; i++){ ans += mu[i]*x/i/i; } return ans; } int main() { //freopen("in.txt","r",stdin); int T; int k; get(); mp.clear(); cin>>T; while(T--) { scanf("%d",&k); LL lo = 1, hi = INF, mid; LL ans = INF; while(lo<=hi){ mid = (lo+hi)/2; if(mp[mid]!=0){///加了map后省了一半的时间,注意使用场景。有时候可能不能用。有时候时间增大。 if(mp[mid]>=k){ ans = mid; hi = mid-1; }else { lo = mid+1; } continue; } if((mp[mid]=solve(mid))>=k){ ans = mid; hi = mid-1; }else lo = mid+1; } printf("%lld\n",ans); } return 0; }
posted on 2017-08-14 20:58 hnust_accqx 阅读(140) 评论(0) 编辑 收藏 举报