Project_Euler-29 题解
题目
思路
如果暴力破解的话会有一个问题,那就是数值过大的问题,那我们就需要通过对数据结构来进行操作,这样的话会让代码变得很臃肿。
优化思路
其实,对于一个数值,我们并不需要要将其计算出结果,只需要将它们表示为二元组的形式就可以,而且可以去重,例如:
4
2
=
2
4
=
(
2
,
4
)
4^2 = 2^4 = (2,4)
42=24=(2,4)
6
4
=
3
6
2
=
(
6
,
4
)
6^4 = 36^2 = (6,4)
64=362=(6,4)
…
我们让其
给定一个数
x
x
x ,假设我们想求出最小的满足其
k
k
k 次幂等于
x
x
x 的值
y
y
y,即:
x
=
y
k
x = y^k
x=yk
我们可以这样做:
从2开始遍历,对于遍历到的每一个值 j j j,我们尝试对其进行平方运算,并记录平方的次数 k k k,截止条件是得出的值小于 x x x,其间,如果发现得到一个等于 x x x的数,说明存在,这个时候返回 j j j,并将次数 k k k保存下来。
这样就得到了一个二元组。
优化代码
由于暴力破解的代码太臃肿了,因此作者没写出暴力的代码,这里之间放出优化代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#define MAX_N 100
#define MAX_M 10000
typedef struct ppower {
int base;
int power;
} PP;
PP prime_powers;
int arr[MAX_M][MAX_M];
int prime[MAX_N + 5];
void init() {
prime_powers.base = 1;
prime_powers.power = 1;
for (int i = 2; i <= MAX_N; i++) {
if (!prime[i]) prime[++prime[0]] = i;
for (int j = 1; j <= prime[0]; j++) {
if (i * prime[j] > MAX_N) break;
prime[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
// 得到最小底数和其对应幂数的代码
int get_base(int x) {
for (int i = 2; i <= MAX_N && i < x; i++) {
int ans = 1;
int temp = i;
while (temp < x) {
temp *= i;
ans++;
if (temp == x) {
prime_powers.base = i;
prime_powers.power = ans;
return i;
}
}
}
prime_powers.base = x;
prime_powers.power = 1;
return x;
}
// 我们没有采用返回结构体的方式,而是定义了一个全局结构体来保存结果
// 这个函数的作用就是返回上一次求底数对应的幂数
int get_power(int x) {
if (x == prime_powers.base) return prime_powers.power;
else -1;
}
int main() {
int ans = 0;
init();
for (int i = 1; i <= 100; i++) {
int base = get_base(i);
int power = get_power(pr);
printf("i: %d -> base = %d, power = %d\n", i, base, power);
}
for (int i = 2; i <= MAX_N; i++) {
// base是底数
int base = get_base(i);
// power是幂数
int power = get_power(base);
for (int j = 2; j <= MAX_N; j++){
if (arr[base][power * j]) {
continue;
} else {
arr[base][power * j] = 1;
ans++;
}
}
}
printf("ans = %d\n", ans);
return 0;
}