• 【校内模拟】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 获取jsp页面中用iframe引入的jsp页面中的值
    spring事务管理
    mysql中将多行数据合并成一行数据
    C语言字符串格式化输出
    gdb无法单步调试
    Linux系统glibc库版本信息查看
    gcc编译命令行依赖库的指定顺序
    HDFS的基础与操作
    搭建Kubernetes容器集群管理系统
    如何在 CentOS 里下载 RPM 包及其所有依赖包
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/9792630.html
Copyright © 2020-2023  润新知