2018 China Collegiate Programming Contest Final (CCPC-Final 2018)

Tony5t4rk發表於2019-03-01

A. Mischievous Problem Setter

Description:

Mr. Sheep is participating in a programming contest. Mr. Panda, the mischievous problem setter gives him some “hints” on the difficulty level of the problems. As problem solving time matters for contestants who solve the same number of problems, it’s always wise to solve from easiest to hardest problems.

Unfortunately, one man’s meat is another man’s poison. People can have different opinions on the difficulty level of the problems. Especially for Mr. Panda, who always underestimates the difficulty level for hard problems, as all problems are considered easy for him…

There are N problems in the contest and the contest will last for M minutes. The ithi^{th} problem has an estimated difficulty DiD_{i} by Mr. Panda, and it costs Mr. Sheep TiT_{i} minutes to solve. Mr.Sheep always solves problems in increasing order of difficulty (i.e., from the easiest problem to the hardest problem estimated by Mr. Panda). How many problems will Mr. Sheep solve at the end of the contest?

Input:

The first line of the input gives the number of test cases, T(1T20)T (1 ≤ T ≤ 20) . T test cases follow.

For each test case, the first line contains two integers N(1N105)N (1 ≤ N ≤ 10^5) and M(1M105)M (1 ≤ M ≤ 10^5) , where NN is the number of problems in the contest and MM is the length of the contest in minutes.

The next line contains NN distinct integers D1,D2,...,DN(1Di105)D_1, D_2, . . . , D_N (1 ≤ D_i ≤ 10^5) representing the difficulty levels estimated by the problem setter.

The following line contains NN integers T1,T2,...,TN(1Ti105)T_1, T_2, . . . , T_N (1 ≤ T_i ≤ 10^5) representing the actual time (in minutes) it costs for Mr. Sheep to solve the problems.

Output:

For each test case, output one line containing “Case x: y”, where x is the test case number (starting from

  1. and y is the number of problems solved by Mr. Sheep after the contest ends.

Sample Input:

2
5 120
5 10 20 35 100
10 20 35 100 100000
13 300
52 55 82 11 62 79 38 8 58 28 1 70 32
27 62 45 77 22 69 34 43 21 43 85 22 36

Sample Output:

Case 1: 3
Case 2: 5

題目連結

nn 道題目每個題目有兩個屬性:難度,解決用時,只能按照難度遞增順序做題,求 mm 分鐘內解體數量

按照難度排序,由於不能跳題,所以直接對每道題目用時求和判斷即可

AC程式碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    int t; cin >> t;
    for (int Case = 1; Case <= t; ++Case) {
        int n, m; cin >> n >> m;
        vector<pair<ll, ll>> arr(n);
        for (auto &it : arr) cin >> it.first;
        for (auto &it : arr) cin >> it.second;
        sort(arr.begin(), arr.end(), [&](pair<ll, ll> k1, pair<ll, ll> k2) {return k1.first < k2.first;});
        ll sum = 0, ans = 0;
        for (auto &it : arr) {
            if (sum + it.second <= m) {
                sum += it.second;
                ans++;
            }
            else break;
        }
        cout << "Case " << Case << ": " << ans << endl;
    }
    return 0;
}

G. Pastoral Life in Stardew Valley

Description:

Mr. Panda and Mrs. Panda is bored of the hustle and bustle of city life. They decide to make a change. They drop everything they belong to and move to a place where they can find real connections with people and nature. Here in Stardew Valley, they start their life as farmers. They are now embarking on tasks of reclaiming wastelands, sowing seeds, and planting trees.

They are now looking for a rectangle area from the reclaimed wasteland to cultivate their first crop. To prevent crops being damaged by annoying crows, they place several scarecrows inside this rectangle area. The scarecrows occupy a rectangle area that is surrounded by the crops. The wasteland is of NN rows and MM columns. They wonder how many different ways to pick a rectangle area and place crops and scarecrows inside the rectangle. As the number can be large, return the answer modulo 109+710^9+7.

Input:

The first line of input gives the number of test cases TT(1T1051 \leq T \leq 10^5). TT test cases follow. Each test case starts with a line consisting of two integers NN, MM (1N,M1051 \leq N, M \leq 10^5), the number of rows and columns of the wasteland.

Output

For each test case, output one line containing “Case x: y”, where x is the test case number (starting from 11) and y is the number of different ways to place the crops and scarecrows, modulo 109+710^9+7.

Sample Input:

3
2 3
3 3
4 4

Sample Output:

Case 1: 0
Case 2: 1
Case 3: 25

題目連結

n×mn\times m 的棋盤上選擇兩個長方形使一個長方形完全包含另一個長方形,求方案數

先考慮選擇兩個長方形的寬

例如在 1×n1\times n 的棋盤中選擇兩個長方形就有 Cn3+Cn4C_{n}^{3}+C_{n}^{4} 種選法

例如在如圖 1×91\times 9 的棋盤上選則兩個長方形就會選擇四個方格來分別代表大小長方形的左右邊界,其中最左最右的兩個方格(如圖 ABA、B 方格)代表大長方形的邊界,中間的兩個方格(如圖 CDC、D 方格)代表小長方形的邊界,所以這樣選法就為 C94C_{9}^{4} (在 99 個方格種選出四個方格),還有另一種小長方形只佔一個方格的情況,即只用選出三個方格中間的方格代表小長方形,這種情況共有 C93C_{9}^{3} 種,這樣就可以把大小長方形的寬統計完了

大小長方形高的統計方法同理,最後把兩個結果相乘即為最終結果

注意特判 n&lt;3n&lt;3m&lt;3m&lt;3 的情況

AC程式碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;

ll C[maxn][5];

void Init() {
    C[0][0] = 1;
    for (int i = 1; i < maxn; ++i) {
        C[i][0] = 1;
        for (int j = 1; j < 5; ++j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    Init();
    int t; cin >> t;
    for (int Case = 1; Case <= t; ++Case) {
        int n, m; cin >> n >> m;
        if (n < 3 || m < 3) {
            cout << "Case " << Case << ": " << 0 << endl;
            continue;
        }
        cout << "Case " << Case << ": " << ((C[n][3] + C[n][4]) % mod) * ((C[m][3] + C[m][4]) % mod) % mod << endl;
    }
    return 0;
}

I. Cockroaches

Description:

There are NN cockroaches in the field. Cockroach ii is located at coordinate (xi,yi)(x_i, y_i). No two cockroaches are located at the same spot. Boss Luo has a powerful pesticide that can instantly kill all cockroaches on the horizontal and vertical line of the spot where it is used. i.e. cockroaches with either the same x coordinate or y coordinate as the pesticide spot will be killed.
Boss Luo wonders how many cockroaches can be killed at most when the pesticide is used in one spot. He is also interested in the number of different subsets of the annihilated cockroaches when the pesticide kills most cockroaches.

Input:

The first line of the input gives the number of test cases, TT (1T1001 \le T \le 100). TT test cases follow.
For each test case, the first line contains an integers NN (1N1051 \le N \le 10^5), the number of cockroaches.
The next NN lines each contains two integers xx and yy (1x,y1091 \le x, y \le 10^9), describing the coordinates of the cockroaches.
For at least 80 test cases, it is guaranteed that N5&ThinSpace;000N \leq 5\,000.

Output

For each test case, output one line containing “Case x: y z”, where x is the test case number (starting from 11), y is the maximum number of cockroaches that can be killed with pesticide applied on one spot, and z is the number of different subsets of the annihilated cockroaches when the pesticide kills most cockroaches.

Sample Input:

2
5
1 2
1 3
2 3
4 5
6 7
3
1 2
2 3
3 1

Sample Output:

Case 1: 3 5
Case 2: 2 3

題目連結

在平面直角座標系上有 nn 個蟑螂(編號為 [1,n][1,n] ),現你可以指定座標系上的任意一個點,和其橫座標或縱座標相同的蟑螂全部被消滅,求出消滅最多蟑螂的集合種類數

先特判 11 個點和 nn 個點橫縱座標都互不相同的情況

之後消滅最多蟑螂有兩種情況(設同一橫座標下最多點數為 best_xbest\_x ,同一縱座標下最多點數為 best_ybest\_y

  1. best_xbest\_x 所在的 xxbest_ybest\_y 所在的 yy 的交點上有 nn 個點其中一點
  2. best_xbest\_x 所在的 xxbest_ybest\_y 所在的 yy 的交點上無 nn 個點其中一點

統計兩種情況的數量即可

AC程式碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    ll t; cin >> t;
    for (ll Case = 1; Case <= t; ++Case) {
        ll n; cin >> n;
        pair<ll, ll> ans;
        vector<pair<ll, ll>> p(n);
        map<ll, ll> cnt_x, cnt_y;
        ll best_x = 0, best_y = 0;
        for (auto &it : p) {
            cin >> it.first >> it.second;
            best_x = max(best_x, ++cnt_x[it.first]);
            best_y = max(best_y, ++cnt_y[it.second]);
        }

        if (cnt_x.size() == 1 || cnt_y.size() == 1) {
            cout << "Case " << Case << ": " << n << " " << 1 << endl;
            continue;
        }
        if (best_x == 1 && best_y == 1) {
            cout << "Case " << Case << ": " << 2 << " " << n * (n - 1) / 2 << endl;
            continue;
        }

        ll cnt_x_1 = 0, cnt_x_2 = 0, cnt_y_1 = 0, cnt_y_2 = 0;
        for (auto &it : cnt_x) {
            if (it.second == best_x) cnt_x_1++;
            else if (it.second == best_x - 1) cnt_x_2++;
        }
        for (auto &it : cnt_y) {
            if (it.second == best_y) cnt_y_1++;
            else if (it.second == best_y - 1) cnt_y_2++;
        }

        ll best = best_x + best_y;
        ll cnt_1 = cnt_x_1 * cnt_y_1, cnt_2 = cnt_x_1 * cnt_y_2 + cnt_x_2 * cnt_y_1;
        for (auto &it : p) {
            int cnt = cnt_x[it.first] + cnt_y[it.second];
            if (cnt == best) {
                cnt_1--;
                cnt_2++;
            }
            else if (cnt == best - 1) cnt_2--;
        }

        if (cnt_1 > 0) cout << "Case " << Case << ": " << best << " " << cnt_1 << endl;
        else cout << "Case " << Case << ": " << best - 1 << " " << cnt_2 << endl;
    }
    return 0;
}

L. Ultra Weak Goldbach’s Conjecture

Description:

In number theory, Goldbach’s conjecture states that every even integer greater than 22 is the sum of two prime numbers. A weaker version of this conjecture states that every odd number greater than 55 is the sum of three prime numbers.
Here is an ultra weak version of Goldbach’s conjecture: every integer greater than 1111 is the sum of six\textbf{six} prime numbers. Can you help to verify or disprove this conjecture?

Input:

The first line of the input gives the number of test cases, TT (1T2001 \le T \le 200). TT test cases follow.
Each test case contains one integer NN (1N10121 \le N \le 10^{12}).

Output

For each test case, output “Case x:” first, where x is the test case number (starting from 11). If the solution exist, output six prime numbers separated by spaces; otherwise output “IMPOSSIBLE” (quotes for clarity) when the solution does not exist. When the solution exists, any valid solution is acceptable.

Sample Input:

5
6
13
200
570
680

Sample Output:

Case 1: IMPOSSIBLE
Case 2: 2 2 2 2 2 3
Case 3: 43 29 31 29 31 37
Case 4: 97 101 103 107 101 61
Case 5: 137 137 107 113 89 97

題目連結

將一個數 nn 分解為 66 個素數之和

首先特判小於等於 1111 的數肯定無法分解(題目也說了)

對於每個大於 1111nn 進行分解,有兩種情況

  1. nn 為偶數,則其可以分為 22 22 22 22n8n-8 ,由於 nn 為偶數,則 n8n-8 也一定為偶數,所以 n8n-8 一定可以分解為兩個素數之和
  2. nn 為奇數,則其可以分為 22 33 22 22n9n-9 ,由於 nn 為奇數,則 n9n-9 一定為偶數,所以 n9n-9 一定可以分解為兩個素數之和

現在只用考慮將一個偶數分解為兩個素數之和

那麼對素數表中的素數暴力列舉判斷剩下的 nn 減去素數之後是否為素數就可以了

由於 nn 的資料範圍較大,所以判定素數的時候就不能用素數表,我這裡直接暴力判斷就過了

如果會 MillerRabinMiller-Rabin 的話還是碼上比較保險

AC程式碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e8 + 5;
typedef long long ll;

bool isPrime[maxn];
vector<int> prime;

bool _isPrime(ll key) {
    for (ll i = 2; i * i <= key; ++i) {
        if (key % i == 0) return false;
    }
    return true;
}

void _sieve() {
    memset(isPrime, true, sizeof(isPrime));
    for (ll i = 2; i < maxn; ++i) {
        if (isPrime[i]) {
            prime.push_back(i);
            for (ll j = i * i; j < maxn; j += i) isPrime[j] = false;
        }
    }
}

void _solve(ll x) {
    for (auto &p : prime) {
        if (_isPrime(x - p)) {
            cout << p << " " << x - p << endl;
            break;
        }
    }
}

int main() {
    _sieve();
    int t; cin >> t;
    for (int Case = 1; Case <= t; ++Case) {
        ll n; cin >> n;
        cout << "Case " << Case << ": ";
        if (n < 12) {
            cout << "IMPOSSIBLE" << endl;
            continue;
        }
        if (n & 1) {
            cout << 2 << " " << 3 << " " << 2 << " " << 2 << " ";
            n -= 9;
        }
        else {
            cout << 2 << " " << 2 << " " << 2 << " " << 2 << " ";
            n -= 8;
        }
        _solve(n);
    }
    return 0;
}

相關文章