Y sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 394 Accepted Submission(s): 47
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).
Then T cases follow, each contains two positive integer n and r described above.
n<=2*10^18,2<=r<=62,T<=30000.
2 10 2 10 3
13 14
例如:n=15,r=5
正整数数列:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ……
当b=2时,去除的数:1 4 9 16 25 36 ……
当b=3时,去除的数:1 8 27 64 125 216 ……
当b=4时,去除的数:1 16 81 256 ……
当b=5时,去除的数:1 32 243 1024 ……
Y数列:2 3 5 6 7 10 11 12 13 14 15 17 18 19 20 21 22 23 24 26 28 29 30 31 ……
下标:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ……
解题思路:本题数据超int(n<=2*10^18,2<=r<=62,T<=30000),若用枚举的方法去除正整数数列中的a^b(2<=b<=r),则会T掉。
给出一个数n,则1~n以内的正整数必定会有被去除的(假设被去除x1个),则这n个数中只有(n-x1)个数在Y数列中;如果想得到n个数在Y数列中,那么我们至少要在这n个数后面加上x1个数,设n1=n+x1,则在1~n1内的数有多少在Y数列中呢(假设有m个在Y数列中,去除了x2个)?如前面所说,在1~n1内的数最多有n个数在Y数列中(即m<=n),此时判断m与n是否相等。如果相等,则Y数列中第n个数为(n+x1);如果不相等,则继续在(n+x1)数后面再加x2个数,继续判断……一直加到某个数M,使得1~M内的数在Y数列中刚好有n个。
怎么才能很快的求出1~n内有多少个数可以表示为a^b(2<=b<=r)?????
下面简单列出一些a^b(2<=b<=r)的值:
a= 1 2 3 4 5 6 7 8 9 10 11
b=2 1 4 9 16 25 36 49 64 81 100 121
b=3 1 8 27 64 125 216 343 512 729 1000 1331
b=4 1 16 81 256 625 1296 2401 4096 6561 10000 14641
b=5 1 32 243 1024 3125 7776 16807 32768 59049 100000 161051
b=6 1 64 729 4096 15625 46656 117649 262144 531441 1000000 1771561
b=7 1 128 2187 16384 78125 279936 823543 2097152 4782969 10000000 19487171
b=8 1 256 6561 65536 390625 1679616 5764801 16777216 43046721 100000000 214358881
b=9 1 512 19683 262144 1953125 10077696 40353607 134217728 387420489 1000000000 2357947691
我们很容易想到依次去除平方数,三次方数,四次方数,五次方数,六次方数,……,r次方数。基本思想是如此,但是我们根据上面列出的值很容易发现:在a^2中出现的数在a^4,a^6,a^8,……中也出现了,在a^3中出现的数在a^6,a^9,……中也出现了………………。这点我们想的可以用容斥原理解决。
代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-4)
#define inf (1<<28)
#define sqr(x) (x) * (x)
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
//用负数方便计算容斥的符号
int prime[19] = {-2, -3, -5, -7, -11, -13, -17, -19, -23, -29, -31, -37, -41, -43, -47, -53, -59, -61, -67};
vector <int> rongchi; //需要用容斥计算的幂值
//容斥原理
void get_rongchi(int r)
{
rongchi.clear();
for(int i = 0; abs(prime[i]) <= r; i++)//枚举幂值为质数的b//
{
int temp = rongchi.size();
for(int j = 0; j < temp; j++)
{
if(abs(prime[i]*rongchi[j]) <= 63)
rongchi.push_back(prime[i]*rongchi[j]);
}
rongchi.push_back(prime[i]);
}
}
//计算1~x的范围内的数有多少存在于Y数列中
long long calculate(long long x)
{
if(x == 1)
return 0;
long long ans = x;
for(int i = 0; i < rongchi.size(); i++)
{
//若a^b=pow(a,b)=x则b=pow(x,1.0/a) ;
//+0.5为了保证精度;-1是暂时不包含1(因为当a=1时,a^b一定会等于1)
long long temp = (long long)(pow(x + 0.5, 1.0/abs(rongchi[i]))) - 1;
//
if(rongchi[i] < 0)
ans -= temp;
else
ans += temp;
}
return ans - 1; //减去刚才没有包含在内的1
}
//迭代法求Y数列的第n个数
long long solve(long long n,int r)
{
get_rongchi(r);
long long ans = n;
while(1)//
{
long long temp = calculate(ans);//保留下来的个数
if(temp == n)
break;
ans += n - temp; //每次加上被删去的数的个数
}
return ans;
}
int main()
{
int r,T;
long long n;
scanf("%d", &T);
while(T--)
{
scanf("%I64d%d", &n, &r);
printf("%I64d\n",solve(n,r));
}
return 0;
}