• Codeforces Round #471 (Div. 2) C. Sad powers


    C. Sad powers

    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    You're given Q queries of the form (L, R).

    For each query you have to find the number of such x that L ≤ x ≤ R and there exist integer numbers a > 0, p > 1 such that x = ap.

    Input

    The first line contains the number of queries Q (1 ≤ Q ≤ 105).

    The next Q lines contains two integers LR each (1 ≤ L ≤ R ≤ 1018).

    Output

    Output Q lines — the answers to the queries.

    Example
    input
    Copy
    6
    1 4
    9 9
    5 7
    12 29
    137 591
    1 1000000
    output
    2
    1
    0
    3
    17
    1111
    Note

    In query one the suitable numbers are 1 and 4.

    这个题目有些难度,主要是压缩时间,需要对数据进行一些处理和分类,首先1e18没有超long long ,先固定指数p,x^p <= 1e18 可以推导出 x <= 10^(18/p) 。若 p = 2, 则有 10^9 个的数字满足条件,若 p >= 3, 则最多有 10^6 的数字满足条件。所以先预处理,把所有不是完全平方数且满足 x^p<=1e18(p>=3) 的x都加入到vector, 排序去重,对于每次查询输出  sqrt(R) - sqrt(L-1) + upper_bound(R) - lower_bound(L)。对于查询x的平方根,用二分查找。

    总的时间复杂度为 (1e6 + Qlog1e18)。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    vector<ll>g;
    
    ll root(ll x)                   //二分查找平方根
    {
        ll left = 0, right = 1e9;
        ll mid,ans;
        while (left<=right)
        {
            mid = (left+right)>>1;
            if (mid*mid<=x)
            {
                ans = mid;
                left = mid+1;
            }
            else right = mid-1;
        }
        return ans;
    }
    
    void init()                                  //预处理p>=3的数
    {
        g.clear();
        for (ll i=2; i<=1e6; i++)
        {
            double t = 1.0*i*i*i;
            ll  s = i*i*i;
            while (t<2e18)
            {
                ll root_s = root(s);
                if (root_s*root_s<s)
                g.push_back(s);
                t *= i;
                s *= i;
            }
        }
        sort(g.begin(),g.end());
        int sz = unique(g.begin(),g.end())-g.begin();
    }
    
    int main()
    {
        init();
        int q;
        scanf("%d",&q);
        ll l,r;
        while (q--)
        {
            scanf("%I64d %I64d",&l,&r);
            int ans1 = upper_bound(g.begin(),g.end(),r) - lower_bound(g.begin(),g.end(),l);
            int ans2 = root(r) - root(l-1);
            printf("%d
    ",ans1+ans2);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    第四百六十九天 how can I 坚持
    第四百六十八天 how can I 坚持
    第四百四十六、七天 how can I 坚持
    第四百四十四、五天 how can I 坚持
    《Java练习题》Java进阶练习题(一)
    《Java练习题》Java习题集五
    《Java知识应用》Java加密方式(MD5)详解
    《Java知识应用》Java加密方式(Base64)详解
    《MySQL数据库》MySQL数据库安装(linux)
    《Java知识应用》Java Json说明和使用(fastjson)
  • 原文地址:https://www.cnblogs.com/youchandaisuki/p/8727575.html
Copyright © 2020-2023  润新知