题目描述
Yellowstar likes integers so much that he listed all positive integers in ascending order,but he hates those numbers which can be written as a^b (a, b are positive integers,2<=b<=r),so he removed them all.Yellowstar calls the sequence that formed by the rest integers“Y sequence”.When r=3,The first few items of it are:
2,3,5,6,7,10......
Given positive integers n and r,you should output Y(n)(the n-th number of Y sequence.It is obvious that Y(1)=2 whatever r is).
输入
The first line of the input contains a single number T:the number of test cases.
Then T cases follow, each contains two positive integer n and r described above.
n<=2*10^18,2<=r<=62,T<=30000.
输出
For each case,output Y(n).
样例输入
210 210 3
样例输出
1314
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int p[18]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61};
const int mxn=63;
long long n,r;
int f[65];
inline long long get(){
char c;while(!isdigit(c=getchar()));
long long v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
return v;
}
inline long long calc(long long x,long long y){
long long cal;
cal=(long long)pow((long double)x+0.5,(1.0)/(long double)y)-1;
return cal;
}
inline long long gets(long long x){
long long num=x;
for(int i=2;i<=mxn;++i){
if(!f[i])continue;
num+=f[i]*calc(x,i);
}
return num-1;
}
inline void work(){
long long ret=n;
long long t=gets(n);
while(t<n){
ret+=n-t;
t=gets(ret);
}
printf("%lld\n",ret);
}
int main(){
int tt=get();
while(tt--){
memset(f,0,sizeof(f));
n=get();r=get();
for(int i=2;i<=mxn;++i){
int g=1,k=i;
for(int j=0;j<18;++j){
if(!(k%p[j])){
if(!(k%(p[j]*p[j])) || p[j]>r){
g=0;break;
}
else g=-g;
}
}
f[i]=g;
}
work();
}
return 0;
}
思路:容易发现,Y序列中的个数为n-a^b的个数(-m),m=Σ(……);容斥想到莫比乌斯反演。据说二分超时。有一个很好的迭代:先找到n的序列中有多少数(k),while(k<n)继续向下找。于是得到结果。