题目大意
给你(n,r),求第(n)个不能被表示为(a^b(2leq bleq r))的数
(nleq 2 imes {10}^{18},rleq 62)
题解
我们考虑二分,求(leq m)的不能被表示为(a^b)的数(f(m))
我们先忽略(1)
我们钦定能被表示为(a^2,a^3,a^5)等(b)为质数的数,贡献为(lfloorsqrt[2]{m} floor-1,lfloorsqrt[3]{m} floor-1cdots),这样也会包含当(b)为合数时的情况,例如(a^4={(a^2)}^2)
但我们算多了,例如(a^3=b^2=c^6),所以我们要减掉(b)为两个不同的质数的积的情况,即(lfloorsqrt[6]{m} floor-1,lfloorsqrt[10]{m}-1 floorcdots)
然后加上(b)为三个不同的质数的积的情况,减掉(b)为四个不同的质数的积的情况……
我们发现(b=x)时容斥系数为(mu(x))
当(b>62)时(lfloorsqrt[b]{m} floor=1),所以不用继续往下算了
还有,开(n)次根号可以用pow,不过要传long double参数进去,不然就会炸精度。
但是这样子还会tle,因为有(30000)组数据
我们发现(f(x)approxsqrt{x})
我们计算出(f(n)),然后每次把(n)加上(n-f(n)),可以很快得到答案
时间复杂度:(O(???))
反正能过且常数巨大就对了
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
int p[100];
int u[100];
int b[100];
int mx[100];
int cnt;
ll n;
int k;
ll fp(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1)
s=s*a;
a=a*a;
b>>=1;
}
return s;
}
ll calc(ll n,ll x)
{
ll s=floor(ld(pow(ld(n),ld(1)/x)));
return s;
}
ll count(ll x)
{
int i;
ll s=0;
ll nw;
for(i=1;i<=62;i++)
if(mx[i]<=k&&u[i])
{
nw=calc(x,i)-1;
if(!nw)
break;
s+=u[i]*nw;
}
return s;
}
void solve()
{
scanf("%lld%d",&n,&k);
ll t=n;
ll s=count(t);
while(1)
{
t+=n-s;
s=count(t);
if(s==n)
break;
}
printf("%lld
",t);
}
int main()
{
int i,j;
cnt=0;
memset(b,0,sizeof b);
u[1]=1;
mx[1]=1;
for(i=2;i<=62;i++)
{
if(!b[i])
{
p[++cnt]=i;
mx[i]=i;
u[i]=-1;
}
for(j=1;j<=cnt&&i*p[j]<=62;j++)
{
b[i*p[j]]=1;
mx[i*p[j]]=mx[i];
if(i%p[j]==0)
{
u[i*p[j]]=0;
break;
}
u[i*p[j]]=-u[i];
}
}
int t;
scanf("%d",&t);
while(t--)
solve();
return 0;
}