Project-Euler-038思维

038题:

题意:

将192分别与1、2、3相乘:

192 × 1 = 192
192 × 2 = 384
192 × 3 = 576

连接这些乘积,我们得到一个1至9全数字的数192384576。我们称192384576为192和(1,2,3)的连接乘积。

同样地,将9分别与1、2、3、4、5相乘,得到1至9全数字的数918273645,即是9和(1,2,3,4,5)的连接乘积。

对于n > 1,所有某个整数和(1,2, … ,n)的连接乘积所构成的数中,最大的1至9全数字的数是多少?

思路:

​ 首先,我们需要需要想到的是确定范围。所求是对于n>1来说,所以乘数最大是4位数(因为5位数的话,乘数✖️1得到一个5位数,乘数✖️2 最小是5位数,5+5大于9)

​ 我们继续缩小范围:

​ 当乘数是1位数的话,被乘数最多乘到9才能满足乘积是9位数

​ 当乘数是2位数的话,被乘数最多乘到4才能满足乘积是9位数

​ 当乘数是3位数的话,被乘数最多乘到3才能满足乘积是9位数

​ 当乘数是4位数的话,被乘数最多乘到2才能满足乘积是9位数

​ 因此我们只需要判断这样的数的乘积链接是否为全数字即可。对于链接,我们可以通过以下算式进行链接乘积:

res = res * (int)(pow(10, (int)log10(乘积))) + 乘积;   //res即链接后的9位数

代码如下:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <inttypes.h>
#include <algorithm>
#define ll int64_t
#define d int32_t
#define mem(a) memset(a, 0, sizeof(a));
#define N 10000
using namespace std;

d book[10];         //用于标记
d maxx = 0;         //存储最终结果

//用于判断数字t,最长乘到n的链接数是否为全数字,如果是返回该全数字,不是返回0
d chooes (d t, d n) {
    mem(book);
    d res = 0;
    d chang = 0;
    for (d i = 1; i <= n; i++) {
        d val = t * i;
        d len = (int)log10(val) + 1;
        d vall = val;
        chang += len;
        while (vall) {
            if (vall % 10 == 0 || book[vall % 10]) {
                return 0;
            }
            book[vall % 10] = 1;
            vall /= 10;
        }
        res = res * (int)(pow(10, len)) + val;
        if (chang == 9) return res;
    }
    return res;
}

//用于遍历1,2,3,4位数
void work(d len, d n) {
    d low = (int)pow (10, len - 1);
    d high = (int)pow (10, len);
    for (d i = low; i < high; i++) {
        d val = chooes(i, n);
        if (val) {
            maxx = max(maxx, val);
        }
    }
}


int main () {
    d p[4] = {1, 2, 3, 4};
    d q[4] = {9, 4, 3, 2};
    for (d i = 0; i < 4; i++) {
        work(p[i], q[i]);
    }
    printf("%" PRId32"\n", maxx);
}

最后结果为:932718654

转载请注明出处!!!

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值