1. 程式人生 > 實用技巧 >DML語言--修改

DML語言--修改

目錄

Codeforces Round #660 (Div. 2)

A. Captain Flint and Crew Recruitment

題意: 給定T個測試樣例,每個測試樣例給定1個數字n,問n是否能夠分成4個不同的數字,4個數字中near prime的個數大於等於3。定義near prime為:兩個素數p和q的乘積,且p < q。如果能的話輸出YES,下一行輸出那4個數字;不能輸出NO。
題解:

由於需要分成4個near prime。而最小的3個near prime為:36、40、44。因此只需要分成6、10、14和n-30。由於要4個數字不同,因此需要特判36、40、44的情況。
程式碼:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    for (int i = 1, t; i <= n; ++i) {
        cin >> t;
        if (t < 31) {
            cout << "NO\n";
            continue;
        }
        else {
            cout << "YES\n";
            if (t == 36) {
                cout << 6 << " " << 10 << " " << 15 << " " << 5 << endl;
                continue;
            }
            else if (t == 40) {
                cout << 6 << " " << 10 << " " << 15 << " " << 9 << endl;
                continue;
            }
            else if (t == 44) {
                cout << 6 << " " << 7 << " " << 10 << " " << 21 << endl;
                continue;
            }
            else {
                cout << 6 << " " << 10 << " " << 14 << " " << t - 30 << endl;
                continue;
            }
        }
    }
    return 0;
}

B. Captain Flint and a Long Voyage

題意: 給定T個測試樣例,每個測試樣例給定一個n,要求輸出一個n位數字。要求輸出的n位數字的產生規則如下:將n位數字的每一位變成二進位制形式,連線在一起,然後刪除最後n個01數字,要求最後剩下的二進位制字串最大,且在不影響答案的前提下,這個n位數字最小。
題解: 由於要然這個n位數字最大,因此要讓二進位制數字儘可能長,因此選擇1001或1000,在沒有被刪除尾數的情況下,儘可能選擇1001。然後因為要刪除尾數,所以如果被刪除的情況下,1001和1000結果一樣,為了儘可能小,選擇1000.因此發現:n在1 ~ 4情況下,最後一個為8,前面的為9;在5 ~ 8情況下,最後兩個為8,前面為9。(因為每4個一組,會讓8和9沒有區別,所以只要看有幾個4組即可,而且通過分析知道是向上取整的)。
程式碼:

#include<bits/stdc++.h>

using namespace std;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        double n;
        cin>>n;
        int limit = ceil(n/4);
        for(int i = 0; i < n - limit; i++) printf("9");
        for(int i = 1; i <= limit; i++) printf("8");
        
        cout<<endl;
    }
    return 0;
}

C. Uncle Bogdan and Country Happiness

題意: 現在有一顆樹,根為1。樹上有m個人,白天的時候這m個人都在1號點工作,晚上回家。這m個人心情可能會在回家的路上變壞。現在給定每個節點好心情-壞心情的人數,且心情只能從好變為壞,問給出的每個節點的好心情-壞心情的人數是否能夠成立,能夠成立輸出YES,不能成立輸出NO。第一行給出測試樣例數目T,每個測試樣例給出n和m。下一行給出n個數字,如果是0表示該點是一個人的家。下一行給出n個數字,表示每個節點的好心情-不好心情人數。下面n-1行給出樹的連邊關係。\(\sum_{}n\) <= 10^5^、\(\sum_{}m\) <= 10^5^
題解: 由於心情只能從好變為壞,因此父節點的好心情人數一定大於等於子節點的好心情人數和。所以可以通過sz[u]和h[u]計算出u節點的好心情人數g[u]和壞心情人數b[u],然後判斷子節點好心情人數和和g[u]的關係即可。
程式碼:

#include <bits/stdc++.h>

using namespace std;

int T, n, m;
int const N = 2e5 + 10;
int g[N], b[N], h[N], p[N], sz[N];
int e[N * 2], ne[N * 2], hh[N], idx;
int flg;

void add(int a, int b) {
    e[idx] = b, ne[idx] = hh[a], hh[a] = idx++;
}

void dfs(int u, int fa) {
    sz[u] = p[u];
    int G = 0;
    for (int i = hh[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (j == fa) continue;
        dfs(j, u);
        sz[u] += sz[j];
        G += g[j];
    }
    
    g[u] = (sz[u] + h[u]) / 2, b[u] = (sz[u] - h[u]) / 2;
    if (g[u] + b[u] != sz[u] || g[u] < 0 || b[u] < 0 || g[u] < G || g[u] - b[u] != h[u]) flg = 0;
    return ;
}

int main() {
    cin >> T;
    while (T--) {
        memset(sz, 0, sizeof sz);
        memset(hh, -1, sizeof h);
        idx = 0;
        flg = 1;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) scanf("%d", &p[i]);
        for (int i = 1; i <= n; ++i) scanf("%d", &h[i]);
        for (int i = 1, a, b; i <= n - 1; ++i) {
            scanf("%d%d", &a, &b);
            add(a, b);
            add(b, a);
        }
        dfs(1, -1);
        if (flg) cout << "YES\n";
        else cout << "NO\n";
    }
    return 0;
}