HDU 5297 Y sequence 容斥 迭代

Y sequence

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=5297

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

Hint

题意

有一个序列,一开始是1,2,3,4,5,....,inf 这样的。

然后这个序列把a^b(1<b<=r)都删除掉了。

现在给你n,r。

问你这个序列的第n项是什么。

题解:

假设我们知道了cal(x)表示包括x在内的x之前这个序列有多少个数。

那么显然我们就可以直接二分乱搞就好了。

然后cal怎么做呢?

x(1/b)就表示x范围内有多少个ab次方的数,然后根据这个容斥一波就好了。

比如你减去了2次方的,减去了3次方的,但是你多减了6次方的,你得加回去。

然后你就做完了。

还有一个问题就是二分会TLE,所以你就只能换成迭代做了……

代码

#include<bits/stdc++.h>
using namespace std;
int prime[100],cnt;
long long n;int m;
vector<int>v;
void init()
{
    int tot=2;
    while(1)
    {
        if(tot>100)break;
        int flag=0;
        for(int i=2;i<tot;i++)
            if(tot%i==0)flag=1;
        if(flag==0)prime[cnt++]=-tot;
        tot++;
    }
}
void init2()
{
    v.clear();
    for(int i=0;-prime[i]<=m;i++)
    {
        int tot = v.size();
        for(int j=0;j<tot;j++)
            if(abs(v[j]*prime[i])<=63)
                v.push_back(v[j]*prime[i]);
        v.push_back(prime[i]);
    }
}
long long cal(long long x)
{
    long long ra = 0;
    for(int i=0;i<v.size();i++)
    {
        long long tmp = exp(log(x+0.5)/abs(v[i]))-1;
        if(v[i]<0)ra=ra+tmp;
        else ra=ra-tmp;
    }
    return x-ra-1;
}
int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%d",&n,&m);
        init2();
        long long ans = n,tmp = cal(n);
        while(tmp<n)
        {
            ans=ans+n-tmp;
            tmp=cal(ans);
        }
        printf("%lld\n",ans);
    }
}
posted @ 2016-03-14 10:26  qscqesze  阅读(326)  评论(0编辑  收藏  举报