[Grupo] mejorar el anillo más pequeño NOI Online

\(Solución\)

Nosotros no interferimos con la secuencia en varios anillos. (Es un no interferente anillos \ (K \) en cualquier caso no a otro anillo)

Puede ser demostrada, nos dividiremos en \ (mcd (n, k) \) anillos, cada anillo tiene ({\ frac {n} \ n, k mcd ()} \) número . (Solución a un problema que mucha gente está tan escrito, pero konjac konjac simplemente no entienden esto)

Luego tratamos de demostrarlo:

En primer lugar, si se trata de un anillo debe ser el mismo en todas partes. Hemos establecido cada anillo tiene \ (x \) número. Luego está: \ (KX \ equiv0 \ (MOD \ n- la) \) .

Nos \ (gcd (n, k) \) El \ (n- \) y \ (K \) se divide en varias pequeña celosía, a continuación, \ (\ frac {n} { gcd (n, k)} \) es \ (n \) hay varios tales pequeña rejilla. Lo multiplicamos por \ (k \) , se debe cumplir \ (k \) y el paseo es alcanzable, entonces para \ (el n- \) , es bastante el \ (\ frac {n} { mcd (n, k)} \) una pequeña capacidad de la red por el \ (gcd (n, k) \) extendido a la \ (K \) a, también satisface las necesidades anteriores de congruencia. (Tenga en cuenta que debe hacer frente a una pequeña capacidad de la red \ (k \) es un factor, a fin de asegurar la multiplicación)

A continuación queremos garantizar es que cada anillo tiene \ (\ frac {n} { mcd (n, k)} \) para cada contar el número de veces que el anillo sólo puede ir una vez. (De hecho, esta descripción no es exacta, ya que aparece el número en sí una sola vez)

Este certificado es realmente muy bueno, porque \ (GCD \) es el mayor factor común, por lo que \ (\ frac {n} { gcd (n, k)} \) es el más pequeño, es decir, \ (X \) .

¿Por qué entonces es la prueba de la orden me puso aquí para poner un hermano mayor: Haga clic aquí para ver los dioses

Fijo respuesta número obligada es la misma, nos ocupamos en una memoria de la misma. (Después de un escaso número de factores que no son muchos)

Consulte el código.

\(Código\)

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;

const int N = 2e5 + 5;

ll a[N], memo[N], ans;
int n, m, k; 

int read() {
    int x = 0, f = 1; char s;
    while((s = getchar()) > '9' || s < '0') if(s == '-') f = -1;
    while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
    return x * f;
}

int gcd(const int a, const int b) {
    if(! b) return a;
    return gcd(b, a % b);
}

int main() {
    n = read(), m = read();
    for(int i = 1; i <= n; ++ i) a[i] = read();
    sort(a + 1, a + n + 1);
    while(m --) {
        k = read();
        ans = 0;
        if(k == 0 || n == 1) {
            for(int i = 1; i <= n; ++ i) ans += a[i] * a[i];
            printf("%lld\n", ans);
            continue;
        }
        int t = gcd(n, k), per = n / t;
        if(memo[per]) {printf("%lld\n", memo[per]); continue;}
        for(int i = 1; i <= n; i += per) {
            for(int j = 0; j < per - 2; ++ j) ans += a[i + j] * a[i + j + 2];//按顺序取,相当是 min,min+2...min+3,min+1 (这是个环)
            ans += a[i] * a[i + 1] + a[i + per - 1] * a[i + per - 2];//取min与min+1,max与max-1
        }
        printf("%lld\n", ans);
        memo[per] = ans;
    }
    return 0;
} 

Supongo que te gusta

Origin www.cnblogs.com/AWhiteWall/p/12456259.html
Recomendado
Clasificación