①莫比乌斯函数本质为容斥系数出发
要求不含平方因子的个数和
容斥表达=1平方的倍数的数(全部数)-2的平方的倍数的数-3的平方的倍数的数+6的平方的倍数的数(减2和3的平方的倍数的时候减多了一部分,加回来)
核心式子:
②由上式的前缀和与要找的数的大小存在有序相关性(第K个数为n,K越大n也越大),可以二分查找,而且T不大,因此每次二分找n时,枚举1~求和。
注意因为有平方因子的数mu=0,所以会有多个数前缀和相等,找到不含平方因子的数的那个作为结果。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 5e6;
const int maxn=1644934081;//
ll mu[N+20],phi[N+20];
int prime[N+20];
int vis[N+20];
inline int read() { //输入挂
int X=0,w=1; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
return X*w;
}
void init()
{
int cnt=0;
mu[1]=1;
for(int i=2;i<=N;i++)//统一ll和int!!!
{
if(!vis[i])
{
prime[++cnt]=i;//++写在前面
mu[i]=-1;//素数 只有它本身一个素因子
}
for(int j=1;prime[j]*i<=N&&j<=cnt;j++)//不越两界
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
//mu[i*prime[j]]=0;//初始化为0所以这项可有可无
break;
}
else
{
mu[i*prime[j]]=-mu[i];//多一个素因子变正负
}
}
}
// for(int i=1;i<=N;i++)mu[i]+=mu[i-1];//前缀和
}
ll check(ll m){
ll ans=0;
ll t=sqrt(m);
for(ll i=1;i<=t;i++){//i一定要写成long long不然死循环
ans+=mu[i]*(m/(i*i));
}
return ans;//和就是个数
}
ll S_mu2(ll n)
{
ll l=1;
ll r=1e10;
ll mid;
ll ans=0;
while(l<=r){
mid=(l+r)/2;
//if(check(mid)==n)return mid;
//不能直接退出,因为尽量选小的 可能后面mu=0,含平方因子
if(check(mid)<n)l=mid+1;
else ans=mid,r=mid-1;
}
return ans;
}
int main()
{
init();
int T=read();
while(T--)
{
ll k=read();
printf("%lld\n",S_mu2(k));
}
return 0;
}