数论(分解质因数) - Mysterious Bacteria - LightOJ 1220

数论(分解质因数) - Mysterious Bacteria - LightOJ 1220

题意:

给 定 正 整 数 x , 求 满 足 条 件 的 最 大 的 指 数 p , 使 得 a p = x , ( a 是 整 数 ) 。 给定正整数x,求满足条件的最大的指数p,使得a^p = x,(a是整数)。 xp使ap=x,(a)

Input

输入包含多组样例T(T≤50),每个样例包括一个整数x,x的范围在32位二进制数以内, 保证x的绝对值大于等于2。

Output

对于每个样例输出最大的指数p。

Sample Input

3
17
1073741824
25

Sample Output

Case 1: 1
Case 2: 30
Case 3: 2

T i m e   l i m i t : 500 m s , M e m o r y   l i m i t : 32768 k B Time \ limit:500 ms,Memory\ limit:32768 kB Time limit500msMemory limit32768kB


分析:

已 知 , 对 任 意 正 整 数 x , 可 分 解 为 x = p 1 a 1 × p 2 a 2 × . . . × p k a k 已知,对任意正整数x,可分解为x=p_1^{a_1}×p_2^{a_2}× ...×p_k^{a_k} xx=p1a1×p2a2×...×pkak

转 化 为 x = a p , 则 p 为 a 1 , a 2 , . . . , a k 的 一 个 公 约 数 , 要 使 得 p 最 大 , 即 求 g c d ( a 1 , a 2 , . . . , a k ) 。 转化为x=a^p,则p为a_1,a_2,...,a_k的一个公约数,要使得p最大,即求gcd(a_1,a_2,...,a_k)。 x=appa1,a2,...,ak使pgcd(a1,a2,...,ak)

注意:

x 可 能 是 负 数 , 我 们 可 取 其 绝 对 值 进 行 因 式 分 解 。 x可能是负数,我们可取其绝对值进行因式分解。 x

但 是 当 x 是 负 数 时 , p 必 然 是 奇 数 。 若 求 得 的 p 是 偶 数 , 我 们 要 不 断 除 2 , 直 到 p 是 奇 数 。 但是当x是负数时,p必然是奇数。若求得的p是偶数,我们要不断除2,直到p是奇数。 xpp2p

当 x = − 2147483648 时 , − x 仍 然 是 − 2147483648 。 当x=-2147483648时,-x仍然是-2147483648。 x=2147483648x2147483648

对 负 数 开 根 号 的 结 果 仍 然 是 − 2147483648 , 这 就 可 能 导 致 不 对 x 进 行 质 因 数 分 解 , 可 能 会 造 成 死 循 环 。 对负数开根号的结果仍然是-2147483648,这就可能导致不对x进行质因数分解,可能会造成死循环。 2147483648x

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>

#define ll long long

using namespace std;

const int N=1e5+10;

int primes[N],cnt;
bool st[N];

void get_prime(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i]) primes[cnt++]=i;
        for(int j=0;primes[j]*i<=n;j++)
        {
            st[primes[j]*i]=true;
            if(i%primes[j]==0) break;
        }
    }
}

int gcd(int a,int b)
{
    return b ? gcd(b,a%b) : a;
}

int solve(ll x)
{
    ll tmp=x;
    if(x<0) x=-x;
    int res=0;
    
    int sqx=sqrt(x);
    for(int i=0;i<cnt && primes[i]<=sqx;i++)
    {
        int p=primes[i];
        if(x%p==0)
        {
            int cnt=0;
            while(x%p==0)
            {
                x/=p;
                cnt++;
            }
            res=gcd(cnt,res);
        }
    }
    
    if(x>1) res=1;
    if(tmp<0)
        while(res%2==0) res/=2;
    return res;
}

int main()
{
    get_prime(N-1);
    
    int T; cin>>T;
    for(int t=1;t<=T;t++)
    {
        ll x; cin>>x;
        printf("Case %d: %d\n",t,solve(x));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值