Project Euler Problem 51:Prime digit replacements【暴力】【按位枚举】【stringstream】

PE其他解题报告请参考这里,本题答案在留言首条

Prime digit replacements

Problem 51

By replacing the 1 s t 1^{st} 1stdigit of the 2-digit number *3, it turns out that six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.

By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit number is the first example having seven primes among the ten generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993. Consequently 56003, being the first member of this family, is the smallest prime with this property.

Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family.


题意:

让你寻找一个素数,替换该素数其中部分位置的数字,替换位置的数字必须是相同的数字,如果替换位置的数字可以找到8个,这个素数就符合题意。类比题目中的:56003, 56113, 56333, 56443, 56663, 56773, and 56993 ,第三四位。

分析:

我们先打个素数表,一开始是前1e5的素数,发现没有符合的,1e6才可以找到符合的。然后暴力的枚举每个素数,然后按位枚举其中的数,如果找到符合满足的数打印即可

参考代码
#include<bits/stdc++.h>

using namespace std;
#define ll long long
const ll maxn = 1e6 + 10;
int f[maxn];
vector<int> p;

/**素数表*/
void init() {
    f[0] = f[1] = 1;
    for(int i = 2; i < maxn; i++) {
        if (!f[i]) {
            p.push_back(i);
            for (int j = i + i; j < maxn; j += i) f[j] = 1;
        }
    }
}

/**每个数的长度*/
int get_len(int x) {
    int l = 0;
    while (x) {l++, x /= 10;}
    return l;
}

bool check(int pri, int bit, int num, int len) {
    stringstream ss;
    string s;
    ss << pri;
    ss >> s;
    /** 特判数字的首位是否为0*/
    if (num == 0 && ((1) & bit)) {
        return 0;
    }
    for (int i = 0; i < len; i++) {
        if ((1 << i) & bit) {
            s[i] = (char)(num + '0');
        }
    }
    ss.clear();
    ss << s;
    ss >> pri;
    return !f[pri];
}

/**打印符合题意的数字*/
void deteil(int pri, int bit, int _min, int len) {
    stringstream ss;
    string s;
    ss << pri;
    ss >> s;
    for (int i = 0; i < len; i++) {
        if ((1 << i) & bit) {
            putchar((char)(_min + '0'));
        } else cout << s[i];
    }
    puts("");
}

int main(){
    init();
    for (auto it : p) {
        int l = get_len(it);
        /**按位枚举*/
        for (int b = 1; b < (1 << l); b++) {
            int cnt = 0;
            int _min = -1;
            for (int i = 0; i < 10; i++) {
                if (check(it, b, i, l)) {
                    cnt++;
                    if (_min == -1) _min = i;
                }
            }
            if (cnt == 8) {
                deteil(it, b, _min, l);
                return 0;
            }
        }
    }
    return 0;
}

阅读好习惯:点赞 + 收藏~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值