1008 立方数 素数筛求约数 stl黑科技 二分 数论

链接:https://ac.nowcoder.com/acm/contest/26656/1008
来源:牛客网

题目描述

对于给定的正整数 N,求最大的正整数 A,使得存在正整数 B,满足 A3B=N
输入包含 T 组数据,1≤T≤10,000;1≤N≤1018

输入描述:

第一行数字 T 表示数据组数
接下来一行,T 个正整数 N

输出描述:

T 行,每行一个数字表示答案
示例1

输入

复制
4
27 24 7 54

输出

复制
3
2
1
3

分析

1e18 的数开三次, 所以考虑在[1,1e6]的数据范围内找数

a^3 *b = x 所以考虑x 的因子中 次数大于等于3 的因子。

但是普通的求约数算法超时了。

所以先用素数筛预处理之后再求约数

但是素数筛1e6  + 求约束也超时。

所以素数筛1e5 + 求约束 + [1e5,1e6] 区间内二分找到最后一个三次的质因子(这个质因子有且只能有一个,所以单独二分求约数后剩下的数就可以了)

重点:首次。我开vector,开map 都是tle,改成数组和cnt 计数就对了。

//-------------------------代码----------------------------

#define int ll
const int N = 1e5+10;
int n,m,primes[N],cnt;
bool st[N];

int qmi(int a,int b) {
    int res = 1;
    while(b) {
        if(b & 1) res = res * a;
        a = a * a ;
        b >>= 1;
    }return res;
}

void solve()
{
    cin>>n;
    map<int,int> mp;
    int ans = 1;
    for(int i = 0;i<cnt;i++) {
        if(n % primes[i] == 0) {
            int cnt = 0;
            while(n % primes[i] == 0) {
                n /= primes[i];
                cnt ++ ;
                if(cnt % 3 == 0) {
                    ans *= primes[i];
                }
            }
        }
    }
    
    int l = 1e5,r = 1e6;
    while( l < r) {
        int mid = l + r  >> 1;
        if(mid * mid * mid == n) {
            ans *= mid;
            break;
        } else if( mid * mid * mid >= n) {
            r = mid;
        } else l = mid + 1;
    }
    cout<<ans<<endl;
}
void get_prime() {
    for(int i = 2;i<=N;i++) {
        if(!st[i]) primes[cnt ++ ] = i;
        for(int j = 0;j < cnt && primes[j] * i <= N;j++) {
            st[primes[j] * i] = 1;
            if(i % primes[j] == 0) break;
        }
    }
}
signed main(){
    clapping();TLE;
    get_prime();
    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

posted @ 2022-07-24 22:19  er007  阅读(41)  评论(0编辑  收藏  举报