HDU 4945 2048

题目链接

题意:给定一个序列,求有多少个子序列能合成2048

思路:把2,4,8..2048这些数字拿出来考虑就能够了,其它数字不管怎样都不能參与组成。那么在这些数字基础上,dp[i][j]表示到第i个数字,和为j的情况数,然后对于每一个数枚举取多少个,就能够利用组合数取进行状态转移,这里有一个剪枝,就是假设加超过2048了,那么后面数字的组合数的和所有都是加到2048上面,能够利用公式一步求解,这种整体复杂度就能够满足题目了。然后这题时限卡得紧啊。10W内的逆元不先预处理出来就超时。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; typedef long long ll;
const int MOD = 998244353; inline void scanf_(int &num)//无负数
{
char in;
while((in=getchar()) > '9' || in<'0') ;
num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
num*=10,num+=in-'0';
} int n, v[2049], mi[15], m, cnt[15];
int dp[15][2049], mi2[100005], invv[100005];
bool istwo[2049]; void init() {
int num;
m = 0;
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < n; i++) {
scanf_(num);
if (!istwo[num]) {
m++;
continue;
}
else cnt[v[num]]++;
}
} int inv(int n) {
int ans = 1;
int k = MOD - 2;
while (k) {
if (k&1) ans = (ll)ans * n % MOD;
n = (ll)n * n % MOD;
k >>= 1;
}
return ans;
} int solve() {
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 1; i <= 12; i++) {
for (int j = 0; j <= 2048; j += mi[i]) {
if (dp[i - 1][j] == 0) continue;
int C = 1, s = 0;
int sum = j;
for (int k = 0; k <= cnt[i]; k++) {
int x = sum;
if (x == 2048) {
dp[i][x] = (ll)dp[i - 1][j] * (mi2[cnt[i]] - s) % MOD + dp[i][x];
if (dp[i][x] < 0) dp[i][x] += MOD;
if (dp[i][x] >= MOD) dp[i][x] -= MOD;
break;
}
if (x % mi[i + 1])
x = x - mi[i];
dp[i][x] = (ll)dp[i - 1][j] * C % MOD + dp[i][x];
if (dp[i][x] >= MOD) dp[i][x] -= MOD;
s += C;
if (s >= MOD) s -= MOD;
C = (ll)C * (cnt[i] - k) % MOD * invv[k + 1] % MOD;
sum += mi[i];
}
}
}
return (ll)dp[12][2048] * mi2[m] % MOD;
} int main() {
memset(istwo, false, sizeof(istwo));
memset(v, -1, sizeof(v));
mi[0] = 0; v[0] = 0;
for (int i = 1, j = 1; i <= 2048; i *= 2, j++) {
istwo[i] = true;
v[i] = j;
mi[j] = i;
}
mi[13] = 4096;
for (int i = 1; i <= 2048; i++) {
if (v[i] == -1)
v[i] = v[i - 1];
}
mi2[0] = 1;
for (int i = 1; i <= 100000; i++) {
invv[i] = inv(i);
mi2[i] = mi2[i - 1] * 2 % MOD;
}
int cas = 0;
while (~scanf("%d", &n) && n) {
init();
printf("Case #%d: %d\n", ++cas, solve());
}
return 0;
}

HDU 4945 2048(DP)的更多相关文章

  1. HDU 4945 2048 DP 组合

    思路: 这个题写了一个背包的解法,超时了.搜了下题解才发现我根本不会做. 思路参见这个: 其实我们可以这样来考虑,求补集,用全集减掉不能组成2048的集合就是答案了. 因为只要达到2048就可以了,所 ...

  2. HDU 4945 2048(dp)

    题意:给n(n<=100,000)个数,0<=a[i]<=2048 .一个好的集合要满足,集合内的数可以根据2048的合并规则合并成2048 .输出好的集合的个数%998244353 ...

  3. hdu 4945 2048 (dp+组合的数目)

    2048 Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submi ...

  4. HDU 4945 (dp+组合数学)

    2048 Problem Description Teacher Mai is addicted to game 2048. But finally he finds it's too hard to ...

  5. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  6. hdu 4507 数位dp(求和,求平方和)

    http://acm.hdu.edu.cn/showproblem.php?pid=4507 Problem Description 单身! 依旧单身! 吉哥依旧单身! DS级码农吉哥依旧单身! 所以 ...

  7. hdu 3709 数字dp(小思)

    http://acm.hdu.edu.cn/showproblem.php?pid=3709 Problem Description A balanced number is a non-negati ...

  8. hdu 4352 数位dp + 状态压缩

    XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. hdu 4283 区间dp

    You Are the One Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

随机推荐

  1. Forbidden You don't have permission to access / on this server.

    原文:Forbidden You don't have permission to access / on this server. Forbidden You don't have permissi ...

  2. ajaxfileupload.js插件结合一般处理文件实现Ajax无刷新上传

    先上几张图更直观展示一下要实现的功能.本功能主要通过Jquery ajaxfileupload.js插件结合ajaxUpFile.ashx一般应用程序处理文件实现Ajax无刷新上传功能,结合NPOI2 ...

  3. ActiveMQ与RabbitMQ采用camel综合

    著名EIP实施框架Camel它起源于ActiveMQ的一些基于消息的集成需求.然后逐渐发展成为一个ActiveMQ的子项目,最后这一块的功能越来越完好.就成为了Apache的顶级项目. 所以,从一開始 ...

  4. 仿jQuery之链式调用

    链式调用的形式其实就是对象调用一连串的方法.为什么能连续调用这么多的方法?因为调用方法返回调用的对象,于是乎就可以一如既往,一往无前地调用下去.链式调用的原理就是在方法中返回执行上下文this,每次调 ...

  5. 《UNIX级别编程环境》注意读出信号(2)

    1.功能sigaction sigaction动与指定信号相关联的处理动作.其函数原型例如以下: #inlcude <signal.h> int sigaction(int signo,c ...

  6. SharePoint 2013 如何使用Silverlight

    1.打开VS,创建一个Silverlight计划.例如下面的附图: 2.配置选择默认的,当然也能够不勾选Host Application,例如以下图: 3.加入Silverlight控件,2个labe ...

  7. HDU 2159 FATE (完全背包+有限尚需时日)()双费背包

     FATE Problem Description 近期xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务.久而久之xhd開始对杀怪产生的厌恶感,但又不得不通过杀怪来升 ...

  8. 终于会用c#中的delegate(委托)和event(事件)了

    一.开篇忏悔 对自己最拿手的编程语言C#,我想对你说声对不起,因为我到现在为止才明白c#中的delegate和event是怎么用的,惭愧那.好了,那今天就趁月黑风高的夜晚简单来谈谈delegate和e ...

  9. java_JFrame_demo

    不要见笑,cs基本入行很少做 留个demo备忘 /* * Copyright (c) 2014-2024 . All Rights Reserved. * * This software is the ...

  10. Javascript闭包的一些研究

    原文:Javascript闭包的一些研究 本文不谈闭包的概念,因为概念容易把人搞晕,本文希望通过几个鲜活的例子来探究闭包的性质,相信对理解闭包会有所帮助. 程序1 var f = (function( ...