Problem
LightOJ1220
Dr. Mob has just discovered a Deathly Bacteria. He named it RC-01. RC-01 has a very strange reproduction system. RC-01 lives exactly x days. Now RC-01 produces exactly p new deadly Bacteria where x = bp (where b, p are integers). More generally, x is a perfect pth power. Given the lifetime x of a mother RC-01 you are to determine the maximum number of new RC-01 which can be produced by the mother RC-01.
Input
Input starts with an integer T (≤ 50), denoting the number of test cases.
Each case starts with a line containing an integer x. You can assume that x will have magnitude at least 2 and be within the range of a 32 bit signed integer.
Output
For each case, print the case number and the largest integer p such that x is a perfect pth power.
Sample Input
3
17
1073741824
25
Sample Output
Case 1: 1
Case 2: 30
Case 3: 2
分析
很自然的想到首先使用唯一分解定理。分过一遍之后,我们可以随便举几个是幂次的数找一找规律。例如324, 324 = 2 2 ∗ 3 4 324=2^2*3^4 324=22∗34,那么很明显,它是 1 8 2 18^2 182,再举一个,108, 108 = 2 2 ∗ 3 3 108=2^2*3^3 108=22∗33那它只能是 10 8 1 108^1 1081,这个规律就出来了。就是求指数的gcd即可。那这个题的另一个坑点是,32比特有符号整数是有正负的,那我们知道,负数的奇数次幂才能使负数,那对于一个负数,先取相反数,按照上面步骤做出答案后将答案不断除以2,以去掉所有偶数的部分即可。
标程
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iomanip>
using namespace std;
#define LL long long
#define endl '\n'
const int MOD = 998244353;
const int INF = 0x3f3f3f3f;
const int N = 1e6;
const int MAXN = 40011;
LL read()
{
LL w = 1, x = 0;
char ch = 0;
while (ch < '0' || ch>'9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + (ch - '0');
ch = getchar();
}
return w * x;
}
LL prime[N / 10 + 7];
bool v[N + 7];
LL cnt = 0;
int flag;
void init()
{
v[0] = v[1] = 1;
for (LL i = 2; i < N; ++i)
{
if (!v[i])
{
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && prime[j] * i <= N; ++j)
{
v[prime[j] * i] = 1;
if (i % prime[j] == 0)
{
break;
}
}
}
}
int gcd(int a, int b)
{
while (b != 0)
{
int t = a % b;
a = b;
b = t;
}
return a;
}
int solve(LL x)
{
int ans = 0;
for (int i = 1; i <= cnt && prime[i] * prime[i] <= x; ++i)
{
int count = 0;
while (x % prime[i] == 0 && x)
{
x /= prime[i];
count++;
}
if (flag)
{
while (count % 2 == 0 && count)
{
count /= 2;
}
}
if (!ans && count)
{
ans = count;
}
else if(count)
{
ans = gcd(ans, count);
}
}
if (x > 1)
{
ans = 1;
}
return ans;
}
int main()
{
init();
// cout << cnt << endl;
int T;
cin >> T;
for (int t = 1; t <= T; ++t)
{
LL n;
n = read();
flag = 0;
if (n < 0)
{
n = -n;
flag = 1;
}
printf("Case %d: %d\n", t, solve(n));
}
return 0;
}