#55021: WHY??????


yp11451159@yphs.tp.edu.tw (705-37陳泓愷)


為什麼測試執行是AC,送出去是WA?

程式如下:

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

const int MAX = 1000005;
bool is_prime[MAX];

void sieve() {
    fill(is_prime, is_prime + MAX, true);
    is_prime[0] = is_prime[1] = false;
    for (int p = 2; p * p < MAX; p++) {
        if (is_prime[p]) {
            for (int i = p * p; i < MAX; i += p)
                is_prime[i] = false;
        }
    }
}

void solve(int n) {
    // 1. 檢查本身是否為質數
    if (is_prime[n]) {
        cout << "1 " << n << endl;
        return;
    }

    // 2. 嘗試拆成 2 個質數 (盡量找靠近中間的)
    if (n % 2 == 0) {
        for (int p = n / 2; p >= 2; p--) {
            if (is_prime[p] && is_prime[n - p]) {
                cout << "2 " << p << " " << n - p << endl;
                return;
            }
        }
    } else {
        // 奇數拆兩個,其中一個必為 2
        if (is_prime[n - 2]) {
            cout << "2 2 " << n - 2 << endl;
            return;
        }

        // 3. 嘗試拆成 3 個質數 (奇數拆 2 不成,則必拆 3 個)
        // 為了使乘積最大,第一個質數儘量小,剩下的偶數部分儘量平分
        for (int p = 2; p < n; p++) {
            if (is_prime[p]) {
                int target = n - p;
                if (target % 2 == 0) { // 剩餘為偶數,嘗試拆成兩個最接近質數
                    for (int q = target / 2; q >= p; q--) { // q 應 >= p 維持非遞減順序
                        if (is_prime[q] && is_prime[target - q]) {
                            cout << "3 " << p << " " << q << " " << target - q << endl;
                            return;
                        }
                    }
                }
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    sieve();
    int n;
    while (cin >> n && n != 0) {
        solve(n);
    }
    return 0;
}

#55022: Re: WHY??????


yp11451159@yphs.tp.edu.tw (705-37陳泓愷)


為什麼測試執行是AC,送出去是WA?

程式如下:

#include
#include
#include

using namespace std;

const int MAX = 1000005;
bool is_prime[MAX];

void sieve() {
    fill(is_prime, is_prime + MAX, true);
    is_prime[0] = is_prime[1] = false;
    for (int p = 2; p * p < MAX; p++) {
        if (is_prime[p]) {
            for (int i = p * p; i < MAX; i += p)
                is_prime[i] = false;
        }
    }
}

void solve(int n) {
    // 1. 檢查本身是否為質數
    if (is_prime[n]) {
        cout << "1 " << n << endl;
        return;
    }

    // 2. 嘗試拆成 2 個質數 (盡量找靠近中間的)
    if (n % 2 == 0) {
        for (int p = n / 2; p >= 2; p--) {
            if (is_prime[p] && is_prime[n - p]) {
                cout << "2 " << p << " " << n - p << endl;
                return;
            }
        }
    } else {
        // 奇數拆兩個,其中一個必為 2
        if (is_prime[n - 2]) {
            cout << "2 2 " << n - 2 << endl;
            return;
        }

        // 3. 嘗試拆成 3 個質數 (奇數拆 2 不成,則必拆 3 個)
        // 為了使乘積最大,第一個質數儘量小,剩下的偶數部分儘量平分
        for (int p = 2; p < n; p++) {
            if (is_prime[p]) {
                int target = n - p;
                if (target % 2 == 0) { // 剩餘為偶數,嘗試拆成兩個最接近質數
                    for (int q = target / 2; q >= p; q--) { // q 應 >= p 維持非遞減順序
                        if (is_prime[q] && is_prime[target - q]) {
                            cout << "3 " << p << " " << q << " " << target - q << endl;
                            return;
                        }
                    }
                }
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    sieve();
    int n;
    while (cin >> n && n != 0) {
        solve(n);
    }
    return 0;
}

這也是:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int MAX = 1000001;
bool is_prime[MAX];

void sieve() {
    fill(is_prime, is_prime + MAX, true);
    is_prime[0] = is_prime[1] = false;
    for (int p = 2; p * p < MAX; p++) {
        if (is_prime[p]) {
            for (int i = p * p; i < MAX; i += p)
                is_prime[i] = false;
        }
    }
}

void solve() {
    int n;
    while (cin >> n && n != 0) {
        // 1. 個數為 1
        if (is_prime[n]) {
            cout << "1 " << n << endl;
            continue;
        }

        // 2. 個數為 2
        bool found2 = false;
        if (n % 2 == 0) {
            // 偶數找最接近 n/2 的兩個質數
            for (int i = n / 2; i >= 2; i--) {
                if (is_prime[i] && is_prime[n - i]) {
                    cout << "2 " << i << " " << n - i << endl;
                    found2 = true;
                    break;
                }
            }
        } else {
            // 奇數拆兩個必含 2
            if (is_prime[n - 2]) {
                cout << "2 2 " << n - 2 << endl;
                found2 = true;
            }
        }
        if (found2) continue;

        // 3. 個數為 3 (只有奇數且 n-2 不為質數時會走到這)
        // 同樣要讓乘積最大,三個數要越接近越好 (接近 n/3)
        bool found3 = false;
        for (int i = n / 3; i >= 2; i--) {
            if (!is_prime[i]) continue;
            int remaining = n - i;
            // 剩下的偶數拆成最接近的兩個質數
            for (int j = remaining / 2; j >= i; j--) {
                if (is_prime[j] && is_prime[remaining - j]) {
                    cout << "3 " << i << " " << j << " " << remaining - j << endl;
                    found3 = true;
                    break;
                }
            }
            if (found3) break;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    sieve();
    solve();
    return 0;
}