Project-Euler-030思维

本文介绍了一种寻找所有能表示为其各位数字五次幂之和的数的方法,并求得这些数的总和。通过确定搜索上限,采用两种算法实现:暴力枚举和深度优先搜索剪枝。最终输出答案为443839。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

跳题是因为有些题简单没有写的必要,或者难度大需要在后面写,循序渐进~

030题:

该题与Project Euler-034和Project Euler-036类似,有时间的童鞋可以看一下那两道题

题意:

有三个数可以写成它们各位数字的四次幂之和:

1634 = 1^4 + 6^4 + 3^4 + 4^4
8208 = 8^4 + 2^4 + 0^4 + 8^4
9474 = 9^4 + 4^4 + 7^4 + 4^4

由于1 = 1^4不是一个和,所以这里并没有把它包括进去。

这些数的和是1634 + 8208 + 9474 = 19316。

找出所有可以写成它们各位数字的五次幂之和的数,并求这些数的和。

思路:

​ 遇到这个题,我们首先需要确定它的上界是什么,不然暴力枚举都不知道终止条件。

​ 对于每一位来说,9^5最大,因此我们通过每位都是9的数来确定它的上界。我们设上限为n

​ 当n为二位数时,最大累计和为六位数; 当n为三位数时,最大累计和为六位数; 当n为四位数时,最大累计和为六位数; 当n为五位数时,最大累计和为六位数; 当n为六位数时,最大累计和为六位数; 当n为七位数时,最大累计和为六位数。

​ 从上边就可以看出,当一个数为7位数及更大,它的最大累计和都不足该数的位数,说明n的上限为6位数。

​ 因此,我有以下两个思路:

​ 思路一:求出6个9^5的和为354294,然后遍历2~354294之间的数,只要满足条件就累加求和,时间复杂度为1e6

​ 思路二:分别求出0~9的五次方(快速幂),然后遍历位数(从2~6),多少位就相当于取多少个数(利用dfs剪枝),只需判断这些数的五次方和是否为与位数相同且等同与这几个数,相同就累加,时间复杂度大概1e5(就相当于有10种球,每种球无限个,同时取2个,3个,4个,5个,6个的方案数,经计算只有7997种)

代码:

​ 老规矩,暴力代码不写:

#include <stdio.h>
#include <string.h>
int num[10];
int ans;
int book1[10], book2[10];
int sss = 0;
//快速幂函数
int quick (int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1)  res *= a;
        a *= a;
        b >>= 1;
    }
    return res;
}
//预处理0~9的五次方
void init () {
    memset (num, 0, sizeof(num));
    for (int i = 0; i < 10; i++) {
        num[i] = quick (i, 5);
    }
}
//dfs剪枝求当为n位数的不同数字组合
void dfs(int now, int inx, int n, int val) {
    if (inx == n) {
        sss ++;       //计算枚举的个数
        memset (book2, 0, sizeof(book2));
        int vall = val, flag = 0;
        while (vall) {
            book2[vall % 10] ++;
            vall /= 10;
        }
        for (int i = 0; i < 10; i ++) {
            if (book1[i] != book2[i]) {
                flag = 1;
                break;
            }
        }
        if (!flag) {
            ans +=val;
        }
        return;
    }
    //剪枝精髓
    for (int i = now; i < 10; i++) {
        book1[i] ++;
        dfs (i, inx + 1, n, val + num[i]);
        book1[i] --;
    }
    return;
}
int main () {
    init();
    ans = 0;
    for (int i = 2; i <= 6; i ++) {
        memset(book1, 0, sizeof(book1));
        dfs(0, 0, i, 0);
    }
    printf("%d\n", ans);
    //printf("%d\n", sss);  //真正枚举的个数,只有7997
    return 0;
}

最后输出答案为: 443839

转载请注明出处!!!

如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值