zoukankan      html  css  js  c++  java
  • 【校内模拟】2048

    题解

    显然(2048)一定是若干个(2^k(0leq k leq 11))凑出来的,我们不妨先将不是(2^k)的数去掉;

    然后考虑求出剩下的数中有多少个子序列能凑出(2048)

    我们可以考虑(DP)(f[i][j])表示前(i)个数凑(j)的方案数,背包就可以,第一维可以滚动数组干掉

    需要注意的一点是所有能凑出大于等于(2048)的数的序列都是合法序列,正确性是显然的(因为构成序列的最大的数也不超过(2048),所有的数都是(2^k)

    不要忘了还有被去掉的数,加上他们依然可以凑出(2048),所以答案是(f[cnt][2048]*(2^{n-cnt}))

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define int long long
    #define MOD 998244353
    #define N 1000010
    int n,a[N],m[2050],cnt,f[2050];
    inline int qpow(int x,int k){
    	int s=1;
    	while(k){
    		if(k&1) s=s*x%MOD;
    		k>>=1;
    		x=x*x%MOD;
    	}
    	return s;
    }
    #undef int
    int main()
    #define int long long
    {
    //	freopen("2048.in","r",stdin);
    //	freopen("2048.out","w",stdout);
    	memset(m,-1,sizeof(m));
    	m[1]=0,m[2]=1,m[4]=2,m[8]=3,m[16]=4,m[32]=5,m[64]=6,m[128]=7,m[256]=8,m[512]=9,m[1024]=10,m[2048]=11;
    	scanf("%lld",&n);
    	int x;
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&x);
    		if(m[x]!=-1) a[++cnt]=x;
    	}
    	f[0]=1;
    	for(int i=1;i<=cnt;i++){
    		for(int j=a[i];j>=1;j--)
    			f[2048]=(f[2048]+f[2048+j-a[i]])%MOD;
    		for(int j=2048;j>=a[i];j--)
    			f[j]=(f[j]+f[j-a[i]])%MOD;
    	}
    	printf("%lld
    ",f[2048]*qpow(2,n-cnt)%MOD);
    	return 0;
    }
    
  • 相关阅读:
    jquery 序列化form表单
    nginx for windows 安装
    nodejs idea 创建项目 (一)
    spring 配置 shiro rememberMe
    idea 2018 解决 双击shift 弹出 search everywhere 搜索框的方法
    redis 在windows 集群
    spring IOC控制反转和DI依赖注入
    redis 的安装
    shiro 通过jdbc连接数据库
    handlebars的用法
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/9792630.html
Copyright © 2011-2022 走看看