Codeforces 1497E2 tamiz lineal + método de selección por regla + DP

Título

Codeforces 1497E2 División sin cuadrados (versión dura)

respuesta

De acuerdo con el teorema básico de la aritmética, sea a = ∑ pieia = \ sum p_i ^ {e_i}a=pagImiyo. Si el producto de dos números es un número cuadrado perfecto, entonces el término exponente ei e_i de los dos númerosmiyoEs el factor primo impar pi p_ipagyoSi el conjunto es el mismo, entonces se puede usar el producto de dichos factores primos ∏ pi \ prod p_ipagyoLa única representación. Tamiz lineal O (N) O (N)O ( N ) preprocesos[1, A] [1, A][ 1 ,A ] es el factor primo más pequeño, luegoO (N log ⁡ A) O (N \ log A)O ( Nlo gA ) Resuelve la representación única de cada elemento.

Luego, las condiciones de restricción en el mismo párrafo se transforman en el único significado de que no hay dos números iguales . Enumere el punto final izquierdo del último párrafo, dp [i] [j] dp [i] [j]d p [ i ] [ j ] representa los subelementos[1, i] [1, i][ 1 ,i ] no cambia más quejjEl número mínimo de segmentos que se pueden dividir entre j números, la complejidad de tiempo total esO (N 2 K 2) O (N ^ 2K ^ 2)O ( N2 K2 )Evidentemente, es difícil hacer el trabajo. ObservarjjCuando j es el mismo,dp [i] [j] dp [i] [j]d p [ i ] [ j ]随着iii aumenta sin disminuir monótonamente, entonces si podemos resolver paraiii es el punto final derecho y no cambia más quejjEl extremo más a la izquierdalb [i] [j] lb [i] [j] de los j dígitos que satisfacen el intervalo condicionall b [ i ] [ j ] , luegoDP DPD P la complejidad del tiempo total se reduce aO (NK 2) O (NK ^ 2)O ( N K2 )
dp [i] [j] = min ⁡ 0 ≤ k ≤ jdp [lb [i] [k] - 1] [j - k] + 1 dp [i] [j] = \ min \ limits_ {0 \ leq k \ leq j} dp [lb [i] [k] -1] [jk] +1d p [ i ] [ j ]=0 k jyod p [ l b [ i ] [ k ]-1 ] [ j-k ]+1 observadojjCuando j es el mismo, cuando el límite derecho del intervalo que satisface la condición se mueve hacia la izquierda, el límite izquierdo no se moverá hacia la derecha, puede usar la reglaO (KN) O (KN)O ( K N )求解lb [i] [j] lb [i] [j]l b [ i ] [ j ]

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200005, maxk = 22, maxa = 10000005, inf = 0x3f3f3f3f;
int T, N, K, A[maxn], id[maxn];
int np, prime[maxa], minp[maxa];
int cnt[maxa], lb[maxn][maxk], dp[maxn][maxk];

void sieve()
{
    
    
    for (int i = 2; i < maxa; ++i)
    {
    
    
        if (!minp[i])
            minp[i] = i, prime[++np] = i;
        for (int j = 1; j <= np && i * prime[j] < maxa; ++j)
        {
    
    
            minp[i * prime[j]] = prime[j];
            if (minp[i] == prime[j])
                break;
        }
    }
}

int main()
{
    
    
    sieve();
    scanf("%d", &T);
    while (T--)
    {
    
    
        scanf("%d%d", &N, &K);
        for (int i = 1; i <= N; ++i)
            scanf("%d", A + i);
        for (int i = 1; i <= N; ++i)
        {
    
    
            int a = A[i], x = 1, cnt = 0, lst = 0;
            while (a != 1)
            {
    
    
                int p = minp[a];
                if (p == lst)
                    ++cnt;
                else
                {
    
    
                    if (cnt & 1)
                        x *= lst;
                    cnt = 1, lst = p;
                }
                a /= p;
            }
            if (cnt & 1)
                x *= lst;
            id[i] = x;
        }
        for (int j = 0; j <= K; ++j)
        {
    
    
            int l = N + 1, sum = 0;
            for (int i = N; i; --i)
            {
    
    
                while (l - 1 >= 1 && sum + (cnt[id[l - 1]] > 0) <= j)
                    --l, sum += cnt[id[l]] > 0, ++cnt[id[l]];
                lb[i][j] = l;
                sum -= --cnt[id[i]] > 0;
            }
        }
        for (int i = 1; i <= N; ++i)
            for (int j = 0; j <= K; ++j)
                dp[i][j] = inf;
        for (int j = 0; j <= K; ++j)
            dp[0][j] = 0;
        for (int i = 1; i <= N; ++i)
            for (int j = 0; j <= K; ++j)
                for (int k = 0; k <= j; ++k)
                    dp[i][j] = min(dp[i][j], dp[lb[i][k] - 1][j - k] + 1);
        printf("%d\n", dp[N][K]);
    }
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/neweryyy/article/details/115266153
Recomendado
Clasificación