Gym

Ultra Weak Goldbach's Conjecture (Gym - 102055L)

题意:

问是否能够把整数N表示为六个素数之和的形式。如果能,给出任一种答案。

题解:

根据哥德巴赫猜想,大约等于4的偶数必然可以被表示为两个素数之和。

所以我们就有了下面两种方法:

  • 2 2 2 + 大素数 + 一个大于等于4的偶数

  • 2 2 3 + 大素数 + 一个大于等于4的偶数

可以先找出小于等于(N-(2+2+2+4))或者(N-(2+2+3+4))的那个大素数,减去后看剩下的部分的奇偶性,根据奇偶性来确定用(2 2 2)还是(2 2 3),以此来保证减去后剩下的数一定是个偶数。

然后暴力把剩下的那个偶数拆分成两个两个素数之和就好了(上面找的那个大素数是靠近N的,所以剩下的这个偶数肯定不会很大)。

判定素数如果暴力的话跑了(1762ms),上了(Miller\_Rabin)素性检测时间锐减到(93ms)

代码

#include <bits/stdc++.h>
#define fopi freopen("in.txt", "r", stdin)
#define fopo freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;

LL mult(LL a, LL b, LL p) {
    a %= p;
    b %= p;
    LL res = 0, tmp = a;
    while(b) {
        if (b & 1) {
            res += tmp;
            if (res > p) res -= p;
        }
        tmp <<= 1;
        if (tmp > p) tmp -= p;
        b >>= 1;
    }
    return res;
}

LL quick_pow(LL a, LL b, LL p) {
    LL res = 1;
    LL tmp = a % p;
    while(b) {
        if (b & 1) res = mult(res, tmp, p);
        tmp = mult(tmp, tmp, p);
        b >>= 1;
    }
    return res;
}

bool check(LL a, LL n, LL x, LL t) {
    LL res = quick_pow(a, x, n);
    LL last = res;
    for (LL i = 1; i <= t; i++) {
        res = mult(res, res, n);
        if (res == 1 && last != 1 && last != n-1) return true;
        last = res;
    }
    return res != 1;
}

bool Miller_Rabin(LL n) {
    if (n < 2) return false;
    if (n == 2) return true;
    if ((n & 1) == 0) return false;
    LL x = n-1;
    LL t = 0;
    while ((x & 1) == 0) {
        x >>= 1;
        t++;
    }

    srand(time(NULL));
    const LL tims = 8;
    for (LL i = 0; i < tims; i++) {
        LL a = rand() % (n-1) + 1;
        if (check(a, n, x, t)) return false;
    }
    return true;
}

pair<LL, LL> Goldbach(LL res) {
    for (LL i = 2; i <= res-2; i++)
        if (Miller_Rabin(i) && Miller_Rabin(res-i)) return {i, res-i};
}

int T;
LL n;
int main() {
    scanf("%d", &T);
    for (int ca = 1; ca <= T; ca++) {
        scanf("%lld", &n);
        printf("Case %d: ", ca);
        if (n <= 11) {
            printf("IMPOSSIBLE
");
            continue;
        }

        LL x = n-10;
        if (!Miller_Rabin(x) || x % 2) while(!Miller_Rabin(x)) x--;

        LL res = n-x;
        if (res % 2 == 0) {
            printf("2 2 2 %lld ", x);
            res -= 6;
            auto p = Goldbach(res);
            printf("%lld %lld
", p.first, p.second);
        } else {
            printf("2 2 3 %lld ", x);
            res -= 7;
            auto p = Goldbach(res);
            printf("%lld %lld
", p.first, p.second);
        }
    }
}
原文地址:https://www.cnblogs.com/ruthank/p/11494495.html