欧拉计划49题

Prime permutations

The arithmetic sequence, 1487, 4817, 8147, in which each of the terms increases by 3330, is unusual in two ways: (i) each of the three terms are prime, and, (ii) each of the 4-digit numbers are permutations of one another.

There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes, exhibiting this property, but there is one other 4-digit increasing sequence.

What 12-digit number do you form by concatenating the three terms in this sequence?

 题目:

1487, 4817, 8147 这个序列,每个比前一个递增 3330,而且这个序列有两个特点:1. 序列中的每个数都是质数。 2. 每个四位数都是其他数字的一种排列。

1,2,3 位组成的三个质数的序列中没有具有以上性质的。但是还有另外一个四位的递增序列满足这个性质。

如果将这另外一个序列的三个数连接起来,组成的 12 位数字是多少?

         题目找的是3个4位数,并且这3个4位数满足以下条件:

        1.每个比前面一个递增3330

        2.每个数都是质数

        3.并且这3个数的每位数的集合是相同的

        那么条件一很好满足,条件二利用线性筛找出10000以下的质数,条件3利用2进制来存储位置上的数,将十进制的数的每位映射到二进制中的位置来表示;

        例如4123将他的每位数字映射在二进制中,

        

        而4231用二进制映射,也是上面途中的这样;

        为什么一个数需要用两位,因为在4位数中如果这个数为质数,那相同的数最多存在3个,所以两位二进制刚好是3;

        那么有了上面这个方法,就很好去判断条件3,就将这3个数分别映射入二进制中,并判读他们映射后的二进制是否相等就可以了;

        映射二进制代码就是:

int map_num(int x) {
    int num = 0;
    while (x){
        num += (1 << (2 * (x % 10)));//因为每两位来表示一个数所以需要乘二
        x /= 10;    
    }
    return num;
}

       最终实现代码为:

#include 
#define MAX_N 10000

int prime[MAX_N + 5];
int isprime[MAX_N + 5];

void init() {//线性筛
    for (int i = 2; 2 * i <= MAX_N; i++) {
        if (!isprime[i]) prime[++prime[0]] = i;
        for (int j = 1; i * prime[j] <= MAX_N; j++) {
            isprime[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    return ;
}

int is_num(int a) {
    int num = 0, s = a;
    while (s) {
        num += (1 << (2 *(s % 10)));
        s /= 10;
    }
    return num;
}

void int_to_char(int a, int b, int c) {
    char buff[15] = {0};
    int len = 0;
    len += sprintf(buff + len, "%d", a);
    len += sprintf(buff + len, "%d", b);
    len += sprintf(buff + len, "%d", c);
    printf("%s\n", buff);
    return ;
}


int main() {
    init();
    for (int i = 1000; i <= MAX_N; i++) {
        if (isprime[i]) continue; //如果当前枚举的数都不为质数继续循环
        if (i == 1487) continue;
        int b = i + 3330;
        int c = i + 6660;
        if (isprime[b] || isprime[c]) continue;//如果b, c有一个不为质数继续循环
        if (is_num(b) != is_num(c)) continue;//如果b, c映射结果不相等继续循环
        if (is_num(i) != is_num(b)) continue;
        int_to_char(i, b, c);
        break;
    }
    return 0;
}

    最终答案:296962999629

你可能感兴趣的:(算法)