cf C. Sad powers 打表暴力所需+二分查找

题目链接–传送门


题意:快速求出L~R中的次幂数个数。 例如 16 = 24 , 16就算一个.
因为数据很大1018 所以我们只需暴力1~1016的次幂大于等于3的即可并且分开偶数次幂,偶数次幂可全当2次幂就行2次幂的数量自己思考一下很简单,最后在区间二分一下有几个数字就行, 二次幂的也可以。

ac代码:

#include <cstdio>
#include <string>
#include <iostream>
#include <map>
#include <cmath>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iterator>

using namespace std;
typedef long long ll;
const ll inf = 1e18;
const ll inn = 1e6;
const ll inx = 1e9;
const ll mx = 1e7+7;

ll tot;
ll su[mx];

ll po(ll a, ll b) {
    ll st = 1;
    while (b){
        if (b&1)
            st *= a;
        a *= a;
		b>>=1;
    }
    return st;
}

void init() {
	tot = 0;
    for (ll i = 1; i <= inn; ++i) {
        ll sq = sqrt((double)i);
        if(i == sq*sq) continue;
        for (ll j = 3; po(i, j-2) <= inf/(i*i); j+=2) {
        	su[tot++] = po(i, j);
		}
    }
    sort(su, su+tot);
    tot = unique(su, su+tot)-su;
}
ll su2(ll a) {
    ll l = 1, r = inx, ans = inx+1;
    while (l <= r) {
        ll mid = (l+r)>>1;
        if (mid*mid >= a) {
            ans = mid;
            r = mid-1;
        }
        else l = mid+1;
    }
    return ans;
}
ll su3(ll a) {
    ll l = 0, r = tot-1, ans = tot;
    while (l <= r) {
        ll mid = (l+r)>>1;
        if (su[mid] >= a) {
            ans = mid;
            r = mid-1;
        }
        else l = mid+1;
    }
    return ans;
}
int main() {
    int q;
    ll l, r;
	init();
	scanf("%d", &q);
    while (q--) {
        scanf("%lld%lld", &l, &r);
        ll sl2 = su2(l), sr2 = su2(r), sum;
        if (sr2*sr2 == r)  sr2++;
        sum = sr2-sl2;
        sl2 = su3(l), sr2 = su3(r);
        if (su[sr2] == r) sr2++;
        sum += sr2-sl2;
        printf("%lld\n", sum);
    }
}
发布了74 篇原创文章 · 获赞 29 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/ClonH/article/details/102857864
sad