【HDU 4945】 2048 Programación dinámica Matemáticas combinatorias

【HDU 4945】 2048 programación dinámica

Título:

Da nnn números, satisfacen0 ≤ ai ≤ 2048 0 \ leq a_i \ leq 20480unayo2 0 4 8 . Se estipulan las nuevas reglas del juego 2048. Para una secuencia, se pueden seleccionar dos números del mismo tamaño de la secuencia cada vez, eliminarlos y luego se agrega un nuevo número que es la suma de los dos números. Si 2048 se puede obtener de esta manera, entonces esta secuencia se llama secuencia perfecta.

Ahora tenemos que contar este nnEl número de secuencias perfectas en todas las subsecuencias de n números. La respuesta es módulo 998244353. (Tenga en cuenta que la definición de subsecuencia es diferente de cadena)

n ≤ 1 × 1 0 5 n \ leq1 \ times10 ^ {5} norte1×1 05


Vale la pena escribir un blog. Es una buena pregunta que hice yo mismo o una pregunta consecutiva ...

Esta vez es lo último.

Quizás el circuito cerebral del autor de esta solución sea un poco ingenuo, y los siguientes "elementos" y "números" se refieren todos a lo mismo. Porque los elementos de la secuencia en esta pregunta son estos números.

Ideas de referencia:

En primer lugar, este tema quiere inducirnos a pensar en las reglas del juego 2048 ... Debemos deshacernos de este punto y repensar.

  • Primero, el número que se puede usar para sintetizar 2048 debe ser una potencia de 2. Se omite la prueba.

  • En segundo lugar, para algunas potencias enteras de 2 (la potencia no excede de 11), siempre que su suma sea mayor o igual a 2048, entonces se debe sintetizar 2048. Esta es una condición necesaria y suficiente, es decir, algunas potencias enteras de 2 (potencias que no excedan de 11) se pueden combinar en 2048, entonces su suma debe ser mayor o igual a 2048.

Tenga en cuenta que el requisito del título no es solo sintetizar 2048, sino poder sintetizar 2048

Durante el juego, fui a dp de frente, pero no lo entendí.

Después del juego, después de la guía del senior, se eligió el método correcto.

Primero, extraemos todos los números de la potencia entera de 2 y los clasificamos y contamos según la potencia. No se pueden usar otros números para sintetizar 2048, pero se pueden usar para construir subsecuencias, por lo que si los otros números tienen kkk , la contribución final a la respuesta es2 k 2 ^ k2k veces, y finalmente multiplicarlo.

Bien, ahora mira el resultado de contar a la potencia de 2. Solo hay 12 tipos de números, solo necesitamos saber el número de cada tipo cnt 2 i cnt_ {2 ^ i}c n t2yo. Porque en esta pregunta, el orden de los elementos en la subsecuencia no tiene nada que ver con la pregunta.

Sabemos que para todas las combinaciones de estos 12 tipos de números (tenga en cuenta que diferentes individuos del mismo tipo de números deben considerarse como elementos diferentes, porque sus subíndices en la secuencia original son diferentes), siempre que la suma combinada sea mayor que 2048 , Se puede incluir en la respuesta; de lo contrario, no se puede incluir en la respuesta.

Somos todo lo contrario, considere cuántas combinaciones de elementos son menores que 2048, y finalmente use el número total de combinaciones 2 n - k 2 ^ {nk}2Solo resta n - k .

Definir dp (i, j) dp (i, j)d p ( yo ,j ) significa que se considera2 0 2 ^ 020 -2 yo 2 ^ yo2En este tipo de elementos, la suma de los elementos seleccionados esjjEl número de planes para j .

转移 方程dp (i, j) = ∑ k = 0 k × 2 i ≤ j C cnt 2 ikdp (i - 1, j - k × 2 i) dp (i, j) = \ sum \ limits_ {k = 0 } ^ {k \ times2 ^ i \ leq j} \ bold C_ {cnt_ {2 ^ i}} ^ {k} dp (i-1, jk \ times2 ^ i)d p ( yo ,j )=k = 0k × 2ijCc n t2yokd p ( yo-1 ,j-k×2yo )

Sea m el número de dígitos en la potencia de 2, entonces la respuesta es:
2 n - m (2 m - ∑ i = 0 2047 dp (11, i)) 2 ^ {nm} (2 ^ m- \ sum \ límites_ {i = 0} ^ {2047} dp (11, i))2n - m (2metro-i = 02 0 4 7d p ( 1 1 ,i ) )

Código de referencia (algunos detalles son diferentes a los anteriores, pero el principio es el mismo)

#define George_Plover
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <iomanip>
#include <algorithm>
#define MAXN 200001
#define MAXM 16000001
#define MOD 998244353
#define LL long long
#define RG register
using namespace std;
int n,m,Case;
int mi[]={
    
    1,2,4,8,16,32,64,128,256,512,1024,2048};
int a[MAXN];
int dp[20][3000];
int cnt[3000];
int fac[MAXN];
int inv_fac[MAXN];
int s[3000];

int qpow(int x,int y)
{
    
    
    x%=MOD;
    int ret=1;
    while(y)
    {
    
    
        if(y&1)
            ret=1ll*ret*x%MOD;
        x=1ll*x*x%MOD;
        y>>=1;
    }
    return ret;
}
int C(int x,int y)
{
    
    
    if(!y)return 1;
    return 1ll*fac[x]*inv_fac[y]%MOD*inv_fac[x-y]%MOD;
}
int main()
{
    
    
    fac[0]=1;
    for(int i=1;i<MAXN;i++)
        fac[i]=1ll*fac[i-1]*i%MOD;

    inv_fac[MAXN-1]=qpow(fac[MAXN-1],MOD-2);
    
    for(int i=MAXN-2;i>=0;i--)
        inv_fac[i]=1ll*inv_fac[i+1]*(i+1)%MOD;
    
    while(scanf("%d",&n)&&n)
    {
    
    
        memset(dp,0,sizeof(dp));
        for(int i=0;i<=11;i++)
            cnt[mi[i]]=0;
        
        int sum=0;
        for(int i=1;i<=n;i++)
        {
    
    
            scanf("%d",&a[i]);
            bool flag=0;
            for(int j=0;j<12;j++)
            {
    
    
                if(a[i]==mi[j])
                {
    
    
                    cnt[a[i]]++;
                    flag=1;
                }
            }
            if(!flag)
                sum++;
        }
        
        for(int i=0;i<=min(cnt[1],2048);i++)
            dp[0][i]=C(cnt[1],i);
        
        for(int i=1;i<12;i++)
        {
    
    
            for(int j=0;j<=2048;j++)
            {
    
    
                for(int k=0;k*mi[i]+j<=2048&&k<=cnt[mi[i]];k++)
                {
    
    
                    dp[i][k*mi[i]+j]+=1ll*dp[i-1][j]*C(cnt[mi[i]],k)%MOD;
                    dp[i][k*mi[i]+j]%=MOD;
                }
            }
        }
        int ans=qpow(2,n-sum);
        for(int i=0;i<2048;i++)
            ans=(ans-dp[11][i])%MOD;
        printf("Case #%d: %lld\n",++Case,(1ll*ans*qpow(2,sum)%MOD+MOD)%MOD);
    }
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/George_Plover/article/details/106305493
Recomendado
Clasificación