现在的位置: 首页 > 综合 > 正文

[CodeChef 13 Feb-CookOff] End Of The World 2

2013年04月17日 ⁄ 综合 ⁄ 共 1987字 ⁄ 字号 评论关闭

URL:

http://www.codechef.com/COOK31/problems/CHEFHCK2

题意:

定义两种数:

1、A^B 形式的(A,B >= 2)

2、非1形式的。

给出一个数x (<= 3141^5)如果是1形式的数求出之前有多少个1形式的数,如果不是1形式的数那么首先倍增2 , 4 。。。。如果落在 2 ^ (k - 1) - 2 ^ k 区间内那么二分,求次数。

解法:

尼玛这是sb题啊!!要什么解法。。

首先预处理 B>=3 的情况, 一共6e5左右个数字。

然后对于第二种Query,暴力就好了。。

Code:

bool _;
LL n;
vector<LL> h;
const LL limit = 305731144433251701ll;
bool isdouble(LL x){
    LL y = sqrt(x);
    return y * y == x;
}
void init(){
    h.clear();
    for (LL i = 3 ; i <= 61 ; i += 2){
        double ii = i;
        for (LL j = 2 ; ; j ++){
            if (isdouble(j)) continue;
            double k = pow(1.*j , 1.*i);
            if (Geo::dblcmp(k - (double)limit) > 0) break;
            LL kk = pow(j , i);
            if (kk <= limit){
                if (!isdouble(kk))
                    h.PB(kk);
            }
            else break;
        }
    }
    UNQ(h);
//    REP(i  , 50) OT(h[i]);
//    cout << h[SZ(h) - 1] << endl;
//    OT(SZ(h));
}
VI :: iterator iter;
LL gao(LL x){
    LL ret = (LL)sqrt((double)x) - 1;
//    OT(ret);
    LL p = lower_bound(ALL(h) , x) - h.begin();
    ret += p + 1;
//    OT(h[p]);
    if (h[p] != x) --ret;
    return ret;
}
bool check(LL x){
    LL p = lower_bound(ALL(h) , x) - h.begin();
    if (h[p] == x) return true;
    p = sqrt(x);
    return (sqr(p) == x);
}
LL A(LL x){
    LL low = 0 , high = limit , mid , ret = high;
    do{
        mid = low + high >> 1;
        if (mid + 1 - gao(mid) < x) low = mid + 1;
        else{
            checkMin(ret , mid);
            high = mid - 1;
        }
    }while(low <= high);
    return ret;
}
LL f(LL x){
    return lg2(cover_bit(x)) + lg2(high_bit(x)) - lg2(low_bit(x));
    //return 2 * lg2(high_bit(x)) - lg2(low_bit(x));
}
LL rev(long long x)
{
	if (x == 0) return 1;
//	printf("\nLess than %lld : %lld\n" , x , gao(x));
    return x - gao(x) + 1;
}
LL solve2(){
    LL low = 0 , high = n * 2 , mid , ret = 0 , now = 1;
//    do{
//        mid = low + high >> 1;
//        LL cc = A(mid);
//        if (cc == n){
//            res = mid;
//            break;
//        }
//        if(cc < n) low = mid + 1;
//        else high = mid - 1;
//    }while(1);
//    LL now = 1 , ret = 0;
        LL res = rev(n);
        /**     Method 1
    do{
        now <<= 1LL;
        ret ++;
    }while(now < res);
    if (now == res) return ret;
    low = now / 2 , high = now;
    do{
        mid = low + high >> 1;
        ++ret;
//        printf("%lld " , mid);OT(now);
        if (mid == res) break;
        if (mid < res) low = mid;
        else high = mid;
    }while(low <= high);
    assert(mid == res);
    return ret;
    */
    return f(res);/** Method 2*/
    /**这两个方法是等价的,都是求要二分多少次*/
}
void solve(){
    RD(n);
    double nn = n;
    LL ans;
    if (n == 0) ans = 2;
    else if (n == 1) ans = 1;
    else{
        if(check(n)) ans = gao(n);
        else {
                ans = solve2();
        }
    }


    if (_) printf(" ");
    _ = true;
    printf("%lld" , ans);
}
int main(){
//    freopen("0.in" ,"r" , stdin);
//    freopen("output.txt" , "w" , stdout);
    _ = false;
    init();
    Rush solve();
    puts("");
}

抱歉!评论已关闭.