Recordar las preguntas del examen escrito de una determinada residencia.

Está chido el examen escrito online de una determinada residencia, así que lo envié para ver si alguien me puede dar algún consejo de cómo solucionar el problema;

1. Tema 1

1.1 Pregunta

Hay dos matrices con longitud n (1 - 5000), es decir, a y b (1 - 10000000). El grado de agrado se define como la suma de ai*bi. Puede elegir un intervalo de b y girarlo una vez para
solicitar el grado máximo de agrado
Ejemplo:
3
10 1 1
1 10 1
Salida:
102
Explicación:
El intervalo de la matriz b invertida es [1, 2], después de voltear es 10 1 1, una matriz es 10 1 1, los bits correspondientes se multiplican y suman hasta 102;

1.2 Ideas de soluciones violentas

Idea:
enumerar los intervalos, para cada intervalo, invertir los elementos en el intervalo en la matriz, calcular el grado similar después de invertir y actualizar el valor máximo, y finalmente generar el grado similar máximo. La complejidad del tiempo es
el código O (n ^ 3):

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

using namespace std;

int main() {
    
    
    int n;
    cin >> n;

    vector<int> a(n);
    vector<int> b(n);
    for (int i = 0; i < n; i++) {
    
    
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
    
    
        cin >> b[i];
    }

    // 计算原始的喜欢程度
    long long ans = 0;
    for (int i = 0; i < n; i++) {
    
    
        ans += (long long)a[i] * b[i];
    }

    // 枚举区间,计算翻转区间后的喜欢程度
    for (int i = 0; i < n; i++) {
    
    
        for (int j = i; j < n; j++) {
    
    
            // 翻转区间
            reverse(a.begin() + i, a.begin() + j + 1);

            // 计算喜欢程度
            long long cur = 0;
            for (int k = 0; k < n; k++) {
    
    
                cur += (long long)a[k] * b[k];
            }

            // 更新最大值
            ans = max(ans, cur);

            // 恢复原数组
            reverse(a.begin() + i, a.begin() + j + 1);
        }
    }

    cout << ans << endl;

    return 0;
}

1.3 Ideas de optimización para la generación de IA

Idea:
puedo proporcionarle una solución basada en un algoritmo codicioso y una optimización de la suma de prefijos, con una complejidad temporal de O (n).

Primero, podemos convertir el producto ai bi a (a+b) (ab), donde a = (ai+bi)/2 y b = (ai-bi)/2. Sólo necesitamos considerar los mayores (a+b) y (ab).

Tomando (a+b) como ejemplo, primero podemos calcular la diferencia entre los dos elementos adyacentes diff[i] = (a[i+1]+b[i+1]) - (a[i]+b [ i]), entonces puedes juzgar si es necesario invertir la posición del intervalo en función del signo de la diferencia. Específicamente, definimos suma1 = a[1]+b[1], suma2 = a[1]-b[1], y luego realizamos un bucle desde la posición i=2:

  • Si diff[i] > 0, significa que a[i]+b[i] es mayor que a[i-1]+b[i-1], lo que significa que hay mejores opciones para los intervalos candidatos posteriores. Registramos maxSum = max(maxSum, sum1+sum2) y marcamos el intervalo [inicio, i] que debe invertirse, y actualizamos suma1 y suma2 al mismo tiempo.
  • Si diff [i] <= 0, significa que es posible que sea necesario agregar la posición actual i-1 al intervalo candidato, y solo necesitamos actualizar suma1 y suma2.

Para la actualización de maxSum, si el intervalo actual que debe invertirse es [inicio, fin], entonces podemos invertir a [inicio], b [inicio] y a [fin], b [fin], es decir, intercambiar a[inicio] y a[fin], intercambie b[inicio] y b[fin] para obtener el nuevo (maxSum, maxA, maxB). Tenga en cuenta que solo necesitamos seleccionar el segmento con el mayor a + b en el intervalo que debe invertirse, pero no necesitamos seleccionar el segmento más grande que debe invertirse. Porque es posible que la diferencia entre algunos intervalos sea muy pequeña y se invierta muchas veces, lo que resultará en una alta complejidad temporal.

Finalmente, necesitamos calcular nuevamente la existencia del intervalo invertido [inicio, fin] y realizar la optimización de la suma de prefijos en a y b respectivamente para calcular rápidamente la suma del intervalo. Específicamente, calculamos los prefijos y sa y sb de a y b respectivamente, y luego el grado de agrado máximo n es igual a a y sa en el intervalo [1, inicio-1], más a y sa en el intervalo [inicio, fin] El valor absoluto de la diferencia, más a y sa en el intervalo [fin+1, n], se multiplica por by sb. Cálculos similares pueden obtener la respuesta.

El código se implementa de la siguiente manera:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
int n, a[MAXN], b[MAXN];
long long sa[MAXN], sb[MAXN];
int diff[MAXN], pos[MAXN];
long long maxSum, maxA, maxB;
void solve()
{
    
    
    sa[0] = sb[0] = pos[0] = 0;
    for (int i = 1; i <= n; ++i) {
    
    
        cin >> a[i] >> b[i];
        sa[i] = sa[i - 1] + a[i];
        sb[i] = sb[i - 1] + b[i];
        pos[i] = i - 1;
        diff[i] = a[i] + b[i] - a[i-1] - b[i-1];
    }
    maxSum = sa[1] + sb[1] + sa[n] - sa[1] + sb[n] - sb[1];
    maxA = sa[1] - sb[1];
    maxB = sb[1] - sa[1];
    int start = 1, end = 0;
    long long sum1 = sa[1] + sb[1], sum2 = sa[1] - sb[1];
    for (int i = 2; i <= n; ++i) {
    
    
        if (diff[i] > 0) {
    
    
            long long tmpSum1 = sum1 + sa[i] - sa[start] + sb[n] - sb[i-1];
            long long tmpSum2 = sum2 + sa[i] - sa[start] - sb[n] + sb[i-1];
            if (tmpSum1 + tmpSum2 > maxSum) {
    
    
                maxSum = tmpSum1 + tmpSum2;
                maxA = tmpSum1 / 2;
                maxB = tmpSum2 / 2;
                if (i <= n - 1 && diff[i+1] <= 0 && sa[i+1]-sa[start] > sb[n]-sb[i]) {
    
    
                    ++i;
                    tmpSum1 += sa[i] - sa[start] - sb[n] + sb[i-1];
                    tmpSum2 += sb[n] - sb[i-1] - sa[i] + sa[start];
                }
                start = pos[i] + 2;
                end = i;
            }
            sum1 += sa[i] - sa[start] + sb[i] - sb[start-1];
            sum2 += sa[i] - sa[start] - sb[i] + sb[start-1];
        } else {
    
    
            sum1 += sa[i] - sa[i-1];
            sum2 += sb[i] - sb[i-1];
            pos[i] = pos[i-1];
        }
    }
    sum1 = sa[n] - sa[start-1];
    sum2 = sb[n] - sb[start-1];
    for (int i = n; i >= end+1; --i) {
    
    
        diff[i] = a[i] + b[i] - a[i-1] - b[i-1];
        if (diff[i] <= 0) {
    
    
            sum1 -= sa[i] - sa[end+1];
            sum2 -= sb[i] - sb[end+1];
        }
    }
    long long answer = abs(sum1*maxB) + abs(sum2*maxA);
    cout << answer << endl;
}
int main()
{
    
    
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n;
    solve();
    return 0;
}

En el código, usamos sa y sb para almacenar la suma del prefijo de a y b, diff almacena la diferencia entre dos elementos adyacentes y pos almacena el extremo izquierdo del intervalo que debe invertirse. Para la actualización de maxSum, también debemos considerar si el intervalo seleccionado actualmente se puede fusionar con intervalos adyacentes posteriores para obtener una mejor opción.

Finalmente, podemos realizar la optimización de la suma de prefijos en a y b respectivamente para calcular rápidamente la suma del intervalo. Al calcular la simpatía, también debemos prestar atención al valor absoluto.

En resumen, la complejidad temporal de este algoritmo codicioso es O (n), que es más eficiente que los métodos de fuerza bruta y los métodos de programación dinámica, y puede resolver problemas con grandes tamaños de datos.

mmd, el código para la idea de optimización no parece correcto, está entumecido.

2. Simular preguntas de cifrado y descifrado

Pregunta:
Para una cadena: kingsoftal abuelo le gusta cifrarla. El método de cifrado es tomar primero la cabeza, luego la cola, hasta terminar. Después de
cifrar según el método de cifrado del abuelo, se ve así: ktifnogsahora el abuelo ha transmitido para usted, necesita descifrar y generar una cadena.
No pensé en ninguna optimización para esta pregunta, así que simplemente invertí el método de cifrado para obtenerla. Lo que debo prestar atención es el problema de obtener caracteres pares e impares, y nada más;

3. Preguntas de programación dinámica

olvidar

Supongo que te gusta

Origin blog.csdn.net/BinBinCome/article/details/131025687
Recomendado
Clasificación