Project_Euler-29 题解

本文介绍了解决ProjectEuler第29题的方法,通过使用数据结构优化暴力破解算法,避免数值过大问题,找到最小的满足给定数k次幂等于x的底数y。作者提供了C语言代码实现,包括初始化素数列表、计算最小底数和对应幂次,以及存储结果的数组优化。
摘要由CSDN通过智能技术生成

Project_Euler-29 题解

标题

题目

1
2

思路

如果暴力破解的话会有一个问题,那就是数值过大的问题,那我们就需要通过对数据结构来进行操作,这样的话会让代码变得很臃肿。

优化思路

其实,对于一个数值,我们并不需要要将其计算出结果,只需要将它们表示为二元组的形式就可以,而且可以去重,例如:

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;
}
好的,我可以为您讲解一下拉格朗日方程的推导过程,以一维情况为例。 假设一个质点在一维坐标系上运动,其位置用 $q$ 表示,时间用 $t$ 表示。该质点的运动可以用拉格朗日函数 $L(q, \dot{q}, t)$ 描述,其中 $\dot{q}=\frac{dq}{dt}$ 表示质点的速度。 为了推导欧拉-拉格朗日方程,我们首先需要定义一个重要的量,即作用量 $S$。作用量定义为 $$S = \int_{t_1}^{t_2} L(q, \dot{q}, t) dt$$ 其中 $t_1$ 和 $t_2$ 表示质点运动的起点和终点。作用量可以理解为一个积分,它是拉格朗日函数在时间 $t_1$ 到 $t_2$ 内的时间积分。 接下来,我们需要考虑如何对作用量进行变分。变分是一种数学操作,它类似于求导,但是是对函数进行微小的偏移,即对函数进行微小的扰动。对于一个作用量 $S$,其变分可以表示为 $$\delta S = S[q+\delta q] - S[q]$$ 其中 $\delta q$ 表示对 $q$ 进行微小的扰动。 现在我们来考虑如何对作用量进行变分。首先,我们将作用量中的积分拆开,得到 $$\delta S = \int_{t_1}^{t_2} \left( \frac{\partial L}{\partial q} \delta q + \frac{\partial L}{\partial \dot{q}} \delta \dot{q} \right) dt$$ 其中第一个式子中的 $\frac{\partial L}{\partial q}$ 表示对 $L$ 关于 $q$ 的偏导数,第二个式子中的 $\frac{\partial L}{\partial \dot{q}}$ 表示对 $L$ 关于 $\dot{q}$ 的偏导数。 现在我们需要将 $\delta \dot{q}$ 转化为 $\delta q$。由于 $\dot{q}=\frac{dq}{dt}$,我们可以得到 $$\delta \dot{q} = \frac{d}{dt} \delta q$$ 将上式代入到 $\delta S$ 中,得到 $$\delta S = \int_{t_1}^{t_2} \left( \frac{\partial L}{\partial q} \delta q + \frac{\partial L}{\partial \dot{q}} \frac{d}{dt} \delta q \right) dt$$ 接下来,我们需要对第二个式子进行分部积分,得到 $$\delta S = \int_{t_1}^{t_2} \left( \frac{\partial L}{\partial q} - \frac{d}{dt} \frac{\partial L}{\partial \dot{q}} \right) \delta q dt + \left[ \frac{\partial L}{\partial \dot{q}} \delta q \right]_{t_1}^{t_2}$$ 现在我们需要对第二个式子进行讨论。由于质点在运动时,其位置 $q$ 和速度 $\dot{q}$ 在起点和终点上都是确定的,因此 $\delta q$ 在 $t_1$ 和 $t_2$ 处的值都应该为 0。因此,第二个式子等于 0。 最终,我们得到了欧拉-拉格朗日方程: $$\frac{d}{dt} \frac{\partial L}{\partial \dot{q}} - \frac{\partial L}{\partial q} = 0$$ 这个方程描述了质点的运动。如果我们能够求出拉格朗日函数 $L$,那么欧拉-拉格朗日方程就可以帮助我们计算质点的运动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若亦_Royi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值