天天看点

LightOJ - 1220 Mysterious Bacteria 唯一分解定理(k次幂数判定)Problem标程

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;
}