CF584D Dima and Lisa

原题链接

  • 题意:给定一个奇数 \(n\),将它表示为之多三个的素数之和。
  • 题解:首先了解,哥德巴赫猜想是当 \(n>=4\) 并且 \(n\) 是一个合数时,必然存在两个素数相加。因此,很容易的是,如果判一下,这个数是素数,那么直接就输出这一个数就可以了。然后,引用一句: 利用的关键性质是这样的:对于两个素数 \(p_1, p_2 \le 10^9\), \(|p_1 - p_2| < 300\). 实际上,最大的差值为 \(282\),因此,设一个数为 \(m\),可以让 \(m\) 从4开始枚举到300,然后一定可以得到 \(n-m\) 是一个质数,\(\because\) 哥德巴赫猜想,当某个数大于等于四,一定存在两个质数相加等于这个数,所以 \(O(300^2)\) 枚举即可。这道题主要考察了对素数密度到 \(1e9\) 的理解与判断。
  • 代码:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;
typedef long long ll;
const ll N = 1e6 + 9;
const ll mod = 1000000007;
ll pr[N];
bool vis[N];
int cnt;
void getpr() {
    for (int i = 2; i < N; i ++) {
        if (!vis[i] )pr[++cnt] = i;
        for (int j = 1; j <=cnt &&pr[j] * i < N; j ++) {
            vis[i * pr[j]] = 1;
            if (i % pr[j] == 0)break;
        }
    }
}
bool ispr(ll n) {
    for (ll i = 2; i * i <= n; i ++) {
        if (n % i==0)return 0;
    }return 1;
}
void solve() {
    getpr();
    ll n = 2;
    cin >> n;
    if (ispr(n)) {
        cout << 1 << "\n" << n << endl;return;
    }
    cout <<3 << endl;
    ll m = 4;
    for (;m <= 300; m ++) {
        if (ispr(n-m)) {
            cout << n-m << " ";break;
        }
    }
    for (ll i = 1; pr[i] <= m; i ++) {
        for (ll j = 1; pr[j] + pr[i] <= m; j ++) {
            if (pr[i] + pr[j] == m) {
                cout << pr[i] << " " << pr[j] << endl;
                return;
            }
        }
    }
    return;
}
signed main() {
    ios::sync_with_stdio(0);
    ll t = 1;
    while (t--) solve();
    return 0;
}
posted @ 2021-03-29 20:55  u_yan  阅读(54)  评论(0编辑  收藏  举报