[2019HDUマルチスクール]第9ラウンド1006 / HDU6685-Rikka with Coin——ビットごとの計算

トピックリンク

トピック

10、20、50、100元のコインの金種を使用して、質問で指定された金種を作成します。コインの最小数が必要です

分析

最初、チームメイトはif-elseの束を使用して問題を解決したいと考えていましたが、WAは無数の投稿を行いました...

私はこの問題を解決する比較的簡単な方法を考えました、そしてこのテーブルの長さは13整数

分析を開始する前に、-1と表示されるソリューションについては考慮しません。つまり、この判断は非常に単純であるため、mod 10が0と等しくない場合があります。

法律

この表を推し進める前に明白な法律を決定してください

同じ数のコインを必要とする2つのスキームがあり、最初のスキームの金種を構成できる場合、2番目のスキームは望ましくありません。

証明:最初のプランのセットを使用する場合、2番目のプランを使用できる必要があります。2番目のプランがこれ以上の額面を形成できない場合でも、この選択は完全に正しいです。

推論

法律によれば、以下の推論が得られます

1. 10元を2つ含む計画などはなく、同様に50元も2つは存在しない

証明:2つの10元を含むプランがある場合、このプランを1つの10元と1つの20元に置き換えることを選択できます。2元で10と20の2つの金種しか構成できないと確信できます。そして、10元と20元は10元、20元、30元の3つの金種を形成することができます。法律によると、このスキームは実行不可能であると判断されています。同様に、2つの50元は50 + 100に置き換えることができます

2. 100元以外の4枚のコインのみが使用され、構成スキームは10、20、20、50と20、20、20、50の2つのみです。

証明:4コインの場合、スキーム10、20、20、50は10〜100のすべてのケースを形成できるため、他のスキームが妥当であれば、100元を超えるケースを形成できる必要があります。コロラリー1によれば、50元は繰り返すことができないため、形成できる最大の値は、20、20、20、50を使用して110を形成することです。

3. 100元以外の5コインは使用されません。

証明:まず、5枚のコインを使用した場合、コロラリー1によると、10、20、20、20、50、または120元と、20、20、20、20、50、または130元の2つの組み合わせしか得られません。したがって、組み合わせが何であっても、結果2の結論は10、20、20、50、100の組み合わせほど良くありません。この組み合わせは、すべてのソリューションを10〜200以内で完了することができるためです。次に、法律によれば、上記の2つの組み合わせは間違った組み合わせです。

4. 110元を超える金種は、1枚または数百枚の硬貨で構成する必要があります。

証明:これは非常に単純で、推論3によって直接導出できます。したがって、110元を超える金種の場合は、上記の条件が満たされるまで-100にしてください。

メートル

そして、せいぜい100元ではないコインが4つしかないことを知っているので、すべての組み合わせを取得できます(0は省略)

1
2
5
1 2
1 5
2 2
2 5
1 2 2
1 2 5
2 2 2
2 2 5
1 2 2 5
2 2 2 5

次に、これらの状況が補うことができる数値を入力します

1
2
5
1 2 3
1 5 6
2 4
2 5 7
1 2 3 4 5
1 2 3 5 6 7 8
2 4 6
2 4 5 7 9
1 2 3 4 5 6 7 8 9 10
2 4 6 7 9 11

ビット操作の助けを借りて、これを行うことができます:

print(1 << 1)
print(1 << 2)
print(1 << 5)
print((1 << 1) + (1 << 2) + (1 << 3))
print((1 << 1) + (1 << 5) + (1 << 6))
print((1 << 2) + (1 << 4))
print((1 << 2) + (1 << 5) + (1 << 7))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 4) + (1 << 5))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 8))
print((1 << 2) + (1 << 4) + (1 << 6))
print((1 << 2) + (1 << 4) + (1 << 5) + (1 << 7) + (1 << 9))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 8) + (1 << 9) + (1 << 10))
print((1 << 2) + (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 9) + (1 << 11))

この表の原理を理解してみると、つまり、各バイトはテーブルの要素として使用されます

最大値は110元に過ぎないことがわかります。最大の金種のコインが100であることに注意してください。また、110元は100元以外、または10元+ 100元で構成できます。同様に、100元の組み合わせは2つあります。したがって、4つの状況を考慮する必要があります。1.
100元は100元で構成され、110元は100元で構成されます2、100元は100元で構成されます。110元は
100元
以外で構成されます。3、100元は100元以外で構成されます。110元4の場合は
100元、非100元の場合100元、非100元の場合は110元を使用します。

次に、すべてについて考えます。どちらか小さい方

ACコード

#include<bits/stdc++.h>

using namespace std;

vector<int> res;

void init() {
    
    
    res.push_back(0);
    res.push_back(2);
    res.push_back(4);
    res.push_back(32);
    res.push_back(14);
    res.push_back(98);
    res.push_back(20);
    res.push_back(164);
    res.push_back(62);
    res.push_back(494);
    res.push_back(84);
    res.push_back(692);
    res.push_back(2046);
    res.push_back(2804);
}

int get_ans(int as) {
    
    
    int t = -1;
    for (int i = 0; i < res.size(); ++i) {
    
    
        if ((res[i] ^ as) + (res[i] & as) == res[i]) {
    
    
            t = i;
            break;
        }
    }
    switch (t) {
    
    
        case 0:
            return 0;
        case 1:
        case 2:
        case 3:
            return 1;
        case 4:
        case 5:
        case 6:
        case 7:
            return 2;
        case 8:
        case 9:
        case 10:
        case 11:
            return 3;
        case 12:
        case 13:
            return 4;
    }
    return 1000;
}

int main() {
    
    
#ifdef ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto start_clock_for_debug = clock();
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin.tie(0);

    int t;
    cin >> t;
    init();
    while (t--) {
    
    
        int n;
        cin >> n;

        int hun[4];
        int cnt[4][15];
        memset(cnt, 0, sizeof(cnt));
        memset(hun, 0, sizeof(hun));
        bool flag = false;

        for (int i = 0; i < n; ++i) {
    
    
            int tmp;
            cin >> tmp;

            if (flag) continue;

            if (tmp % 10) {
    
    
                flag = true;
                continue;
            }
            // 100 + 110
            int tmp0 = tmp;
            if (tmp0 % 100 > 10 and tmp0 > 100) {
    
    
                hun[0] = max(tmp0 / 100, hun[0]);
                tmp0 %= 100;
                cnt[0][tmp0 / 10]++;
            } else if (tmp0 > 100) {
    
    
                hun[0] = max((tmp0 - 100) / 100, hun[0]);
                tmp0 %= 100;
                cnt[0][tmp0 / 10 + 10]++;
            } else {
    
    
                cnt[0][tmp0 / 10]++;
            }
            // 100
            int tmp1 = tmp;
            if (tmp1 % 100 == 0 and tmp1 > 100) {
    
    
                hun[1] = max((tmp1 - 100) / 100, hun[1]);
                cnt[1][10]++;
            } else {
    
    
                hun[1] = max(tmp1 / 100, hun[1]);
                cnt[1][(tmp1 % 100) / 10]++;
            }
            // 110
            int tmp2 = tmp;
            if (tmp2 % 100 == 10 and tmp2 > 100) {
    
    
                hun[2] = max((tmp2 - 100) / 100, hun[2]);
                cnt[2][11]++;
            } else {
    
    
                hun[2] = max(tmp2 / 100, hun[2]);
                cnt[2][(tmp2 % 100) / 10]++;
            }
            // None
            int tmp3 = tmp;
            hun[3] = max(tmp3 / 100, hun[3]);
            cnt[3][(tmp3 % 100) / 10]++;
        }
        if (flag) {
    
    
            cout << -1 << endl;
            continue;
        }
        int ans;
        int get_ans[4];

        for (int j = 0; j < 4; ++j) {
    
    
            ans = 0;
            for (int k = 1; k < 13; ++k) {
    
    
                if (cnt[j][k]) {
    
    
                    ans += 1 << k;
                }
            }
            get_ans[j] = get_ans(ans) + hun[j];
        }
        sort(get_ans, get_ans + 4);
        cout << get_ans[0] << endl;
    }
#ifdef ACM_LOCAL
    auto end_clock_for_debug = clock();
    cerr << "Run Time: " << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
#endif
    return 0;
}

おすすめ

転載: blog.csdn.net/m0_43448982/article/details/99949169