[数论] BZOJ2440 完全平方数
@(ACM题目)[数论|莫比乌斯函数]
二分答案,于是问题转化为求[1,n]中合法的数字的个数。
容斥一下,在全部的n个数字中减去含
p2i1
因子的数个数,再加上含
p2i1p2i2
因子的数的个数,再减去含
p2i1p2i2p2i3
因子的数的个数……再加上含
(−1)kp2i1p2i2…p2ik
因子的数的个数
注意到此处的
(−1)k
恰好是莫比乌斯函数。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define pb push_back
using namespace std;
typedef long long LL;
const int maxn = 1e7+5;
bool isPrime[maxn];
int primes[maxn], mu[maxn], cnt = 0;//primes数组个数小于maxn;cnt为素数个数
void mobius_sieve() {
memset(isPrime, true, sizeof isPrime);
mu[1] = 1;
cnt= 0;
for (int i = 2; i < maxn; ++i)
{
if (isPrime[i]) primes[cnt++] = i, mu[i] = -1;
static int d;
for (int j = 0; j < cnt && (d = i * primes[j]) < maxn; ++j)
{
isPrime[d] = false;
if (i % primes[j]) mu[d] = -mu[i];
else
{
mu[d] = 0;
break;
}
}
}
}
LL k;
bool check(LL n)
{
LL tot = n;
LL sqrtn = sqrt(n);
for(LL i = 2; i <= sqrtn; i++) tot += mu[i]*(n/(i*i));
return tot>=k;
}
int main()
{
mobius_sieve();
int T;
cin>>T;
while(T--)
{
cin>>k;
LL l = 0, r = 2e9+10;
while(l + 1 < r)
{
LL mid = (l+r)>>1;
if(check(mid)) r = mid;
else l = mid;
}
cout<<r<<endl;
}
return 0;
}