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(""); }