【HDU 4945】 2048 Dynamic Programming Combinatorial Mathematics

【HDU 4945】 2048 dynamic programming

Title:

Gives nnn numbers, satisfy0 ≤ ai ≤ 2048 0\leq a_i\leq 20480ai2 0 4 8 . The new 2048 game rules are stipulated. For a sequence, two numbers of the same size can be selected from the sequence each time, eliminated, and then a new number that is the sum of the two numbers is added. If 2048 can be obtained in this way, then this sequence is called a perfect sequence.

Now we need to count this nnThe number of perfect sequences in all subsequences of n numbers. The answer is modulo 998244353. (Note that the definition of subsequence is different from string)

n ≤ 1 × 1 0 5 n\leq1\times10^{5} n1×105


It’s worth writing a blog. It’s either a good question that I made by myself or a back-to-back question...

This time it is the latter.

Maybe the author's brain circuit of this solution is a bit naive, and the following "elements" and "numbers" all refer to the same thing. Because the elements of the sequence in this question are these numbers.

Reference ideas:

First of all, this topic wants to induce us to think about the rules of the 2048 game...We must get rid of this point and rethink.

  • First, the number that can be used to synthesize 2048 must be a power of 2. The proof is omitted.

  • Secondly, for some integer powers of 2 (the power does not exceed 11), as long as their sum is greater than or equal to 2048, then 2048 must be synthesized. This is a necessary and sufficient condition, that is, some integer powers of 2 (powers not exceeding 11) can be combined into 2048, then their sum must be greater than or equal to 2048.

Note that the requirement of the title is not just to synthesize 2048, but to be able to synthesize 2048

During the game, I went to dp head-on, but didn't get it out.

After the game, after the guidance of the senior, the correct method was chosen.

First, we extract all the numbers of the integer power of 2 and classify and count according to the power. Other numbers cannot be used to synthesize 2048, but they can be used to construct subsequences, so if the other numbers have kkk , the final contribution to the answer is2 k 2^k2k times, and finally multiply it up.

Okay, now see the result of counting to the power of 2. There are only 12 types of numbers, we only need to know the number of each type cnt 2 i cnt_{2^i}cnt2i. Because in this question, the order of the elements in the subsequence has nothing to do with the question.

We know that for all combinations of these 12 types of numbers (note that different individuals of the same type of numbers should be regarded as different elements, because their subscripts in the original sequence are different), as long as the combined sum is greater than 2048 , It can be included in the answer, otherwise it cannot be included in the answer.

We are just the opposite, consider how many combinations of elements are less than 2048, and finally use the total number of combinations 2 n − k 2^{nk}2Just subtract n k .

Define dp (i, j) dp(i,j)dp(i,j ) means that2 0 2^0 is considered20- 2 i 2^i 2i these kinds of elements, the sum of the selected elements isjjThe number of plans for j .

转移方程 d p ( i , j ) = ∑ k = 0 k × 2 i ≤ j C c n t 2 i k d p ( 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,j-k\times2^i) dp(i,j)=k=0k×2ijCcnt2ikdp(i1,jk×2i)

Let the number of digits in the power of 2 be m, then the answer is:
2 n − m (2 m − ∑ i = 0 2047 dp (11, i)) 2^{nm}(2^m-\sum\ limits_{i=0}^{2047}dp(11,i))2nm(2mi=02047dp(11,i))

Reference code (some details are different from the above, but the principle is the same)

#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;
}

Guess you like

Origin blog.csdn.net/George_Plover/article/details/106305493