[2019HDU multi-school] Novena ronda 1006 / HDU6685-Rikka con Coin —— Cálculo bit a bit

Enlace de tema

Tema

Se pueden usar denominaciones de monedas de 10, 20, 50, 100 yuanes para formar las denominaciones dadas en la pregunta, y se requiere la cantidad mínima de monedas

análisis

Al principio, los compañeros de equipo querían usar un montón de if-else para resolver el problema, y ​​luego WA hizo innumerables publicaciones ...

Pensé en una forma relativamente simple de resolver este problema, y ​​la longitud de esta tabla es solo13 int

Antes de comenzar el análisis, no consideremos la solución que aparece -1. Es decir, hay una situación en la que mod 10 no es igual a 0, porque este juicio es muy simple

ley

Determine una ley obvia antes de comenzar a empujar esta tabla

Si hay dos esquemas que requieren el mismo número de monedas y se pueden componer las denominaciones del primer esquema, el segundo esquema no es deseable.

Prueba: si uso el primer conjunto de planes, entonces debo poder usar el segundo plan. Incluso si el segundo plan no puede formar más denominaciones, esta elección es completamente correcta.

inferencia

Según la ley, se pueden obtener las siguientes inferencias

1. No existe un plan que contenga dos de 10 yuanes y, de manera similar, dos de 50 yuanes no existen

Prueba: si hay un plan que contiene dos de 10 yuanes, podemos optar por reemplazar este plan con uno de 10 yuanes y uno de 20 yuanes. Podemos estar seguros de que dos de 10 yuanes solo pueden formar las dos denominaciones de 10 y 20. Y 10 yuanes y 20 yuanes pueden formar tres denominaciones de 10 yuanes, 20 yuanes y 30 yuanes. Según la ley, se determina que este esquema no es factible. Del mismo modo, dos 50 yuanes pueden ser reemplazados por 50 + 100

2. Solo se utilizan 4 monedas distintas de 100 yuanes, y solo hay dos esquemas de composición: 10, 20, 20, 50 y 20, 20, 20, 50

Prueba: para 4 monedas, los esquemas 10, 20, 20 y 50 pueden formar todas las cajas de 10-100, por lo que si cualquier otro esquema es razonable, debe poder formar una caja de más de 100 yuanes. Según el Corolario 1, 50 yuanes no se pueden repetir, por lo que el valor más grande que se puede formar es usar 20, 20, 20 y 50 para formar 110.

3. No se utilizan 5 monedas distintas de 100 yuanes

Prueba: Primero, si se usan 5 monedas, según el Corolario 1, solo hay dos combinaciones que se pueden obtener: 10, 20, 20, 20, 50 o 120 yuanes, y 20, 20, 20, 20, 50 o 130 yuanes. Entonces, no importa cuál sea la combinación, la conclusión del Corolario 2 no es tan buena como la combinación de 10, 20, 20, 50, 100, porque esta combinación puede completar todas las soluciones dentro de 10-200. Entonces, de acuerdo con la ley, las dos combinaciones anteriores son combinaciones incorrectas.

4. Las denominaciones superiores a 110 yuanes deben estar compuestas por una o varias monedas de 100 yuanes.

Prueba: Esto es muy simple y puede derivarse directamente del razonamiento 3. Por lo tanto, para denominaciones superiores a 110 yuanes, continúe a -100 hasta que se cumplan las condiciones anteriores.

Por metro

Entonces sabemos que solo hay 4 monedas que no son 100 yuanes como máximo, entonces podemos obtener todas las combinaciones (omitir 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

Luego, podemos escribir los números que pueden formar estas situaciones.

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

Con la ayuda de operaciones de bits, podemos hacer esto:

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))

Puede intentar comprender el principio de esta tabla,Es decir, cada bocado se utiliza como elemento de la mesa.

Se puede ver que el valor máximo es de solo 110 yuanes. Y observe que la moneda con la denominación más grande es 100. Y 110 yuanes pueden estar compuestos por no 100 yuanes o 10 yuanes + 100 yuanes De manera similar, hay dos combinaciones de 100 yuanes. Por lo tanto, deben tenerse en cuenta cuatro situaciones: 1.
100 yuanes se componen de 100 yuanes, 110 yuanes se componen de
100 yuanes 2, 100 yuanes se componen de
100 yuanes, 110 yuanes se componen de no 100 yuanes, 3, 100 yuanes se componen de no 100 yuanes, 110 yuanes Use 100 yuanes por 4,
100 yuanes por no 100 yuanes, 110 yuanes por no 100 yuanes

Entonces piénselo todo, lo que sea más pequeño

Código 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;
}

Supongo que te gusta

Origin blog.csdn.net/m0_43448982/article/details/99949169
Recomendado
Clasificación