Description
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).
Input
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.
Output
For each case,output Y(n).
Sample Input
2
10 2
10 3
Sample Output
13
14
题意:给定整数n和整数r,在1、2、3、4、5…….的序列中删掉可以开2次方的数,3次方的数,4次方的数,…….r次方的数,剩下的数称为Y序列,求Y序列中第n个数是多少 。
解法:
一:首先删去所有的平方数。有n^(1/2)个。再删去所有的三次方数。有n^(1/3)个 …… 这样枚举幂数b(从2开始),然后删去n^(1/b)个数,但是有重复的,比如某个数的6次方可能被平方数删去了一次,又被3次方数删去了一次,于是想到用容斥原理加回来。
二:然后我们来考虑一种情况4,他是2*2他的两个质因子相同。但是他是没必要考虑的。。因为我们在删除2的幂的个数时,他已经被删除了。比如4以内4方的个数,这个肯定比4以内2的方的个数少,而且这些数肯定也是2次放的数,已经被删除过了。没必要再删了。也不用加回来。所以对于质数中有两个或以上的相同的质因子的数我们不需要考虑,只需要考虑质因子都只是一个的时候。(不同组合就好了)
三:同时我们要考虑个数的问题。比如2*3==6这中,它被2删了,有被3删了。对于6我们要加回来,显然是奇数个的时候减去,偶数个的时候加,将最开始的质数用负数表示,这样就可以直接让奇数个为负,偶数个为正(666啊)。
四:在[1,x]之间能开b次方的数的个数为:pow( x , 1/b)。注意精度修正.
五:迭代求解,我们可以想求出前n个,那么我们可以求x以内有几个,如果不是n那么我就让x加上我要求的个数与实际个数的差值(结果只可能还在小),反复如此操作,知道x以内的个数是n为止。
六:每一次abs(prime[i]*Q[j])<=63的都要加入vector。因为我们只要考虑我们去的质因子比r小就行,而比r小的质因子的组合是要考虑的加减的比如r==3时2,3去掉之后,我们得吧6加回来,所以得考虑,但是63以上的那种数我们是不会删的,所以我们也不需要去考虑。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
int prime[66]={-2,-3,-5,-7,-11,-13,-17,-19,-23,-29,-31,-37,-41,-43,-47,-53,-59,-61,-67};
vector<int>Q;
void getyue(int r){
Q.clear();
for(int i=0;abs(prime[i])<=r;i++){
int num=Q.size();
for(int j=0;j<num;j++){
if(abs(prime[i]*Q[j])<=63) Q.push_back(prime[i]*Q[j]);
}
Q.push_back(prime[i]);
}
}
LL calc(LL x){
if(x<=1) return 0;
LL ans=x-1;//除去1
for(int i=0;i<Q.size();i++){
if(Q[i]<0) ans-=(LL)pow(x+0.5,1.0/abs(Q[i]))-1;//除去1
else ans+=(LL)pow(x+0.5,1.0/abs(Q[i]))-1;
}
return ans;
}
LL diedai(LL n){
LL num=n;
LL temp=calc(num);
while(temp!=n){
num+=n-temp;
temp=calc(num);
//cout<<calc(num)<<endl;
}
return num;
}
int main(){
LL n,r,t;
cin>>t;
while(t--){
cin>>n>>r;
getyue(r);
cout<<diedai(n)<<endl;
}
return 0;
}