HDU 4945 2048(DP)
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)的更多相关文章
- HDU 4945 2048 DP 组合
思路: 这个题写了一个背包的解法,超时了.搜了下题解才发现我根本不会做. 思路参见这个: 其实我们可以这样来考虑,求补集,用全集减掉不能组成2048的集合就是答案了. 因为只要达到2048就可以了,所 ...
- HDU 4945 2048(dp)
题意:给n(n<=100,000)个数,0<=a[i]<=2048 .一个好的集合要满足,集合内的数可以根据2048的合并规则合并成2048 .输出好的集合的个数%998244353 ...
- hdu 4945 2048 (dp+组合的数目)
2048 Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submi ...
- HDU 4945 (dp+组合数学)
2048 Problem Description Teacher Mai is addicted to game 2048. But finally he finds it's too hard to ...
- hdu 4123 树形DP+RMQ
http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...
- hdu 4507 数位dp(求和,求平方和)
http://acm.hdu.edu.cn/showproblem.php?pid=4507 Problem Description 单身! 依旧单身! 吉哥依旧单身! DS级码农吉哥依旧单身! 所以 ...
- hdu 3709 数字dp(小思)
http://acm.hdu.edu.cn/showproblem.php?pid=3709 Problem Description A balanced number is a non-negati ...
- hdu 4352 数位dp + 状态压缩
XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu 4283 区间dp
You Are the One Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
随机推荐
- Android: Receiving Data from the Send Intent,自己app注册系统分享
当用户在系统的专辑,点击共享时.通过我们自己的app.分享此图片. 1.注册 主要是在AndroidManifest.xml中,对activity注冊Intent-filter.如: <acti ...
- nodejs中使用monk訪问mongodb
mongodb 安装mongodb 我认为还是用mannual install靠谱一点儿:http://docs.mongodb.org/manual/tutorial/install-mongodb ...
- BZOJ 1901 Zju2112 Dynamic Rankings
树阵主席设置树.维护间隔动态K大. .. ZOJ到空间太小,太大,仅仅能到BZOJ上交 1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memor ...
- android tv 全屏幕垂直画
它们的定义view 采纳canvas双缓冲方式,它可以减少呈现时间.提高性能. StaggeredView.java 源码例如以下: package com.xxx.demo; import andr ...
- js中的open和showModalDialog
一.window.open()支持环境: JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法:window.open(pageURL,name,p ...
- 经典算法题每日演练——第十七题 Dijkstra算法
原文:经典算法题每日演练--第十七题 Dijkstra算法 或许在生活中,经常会碰到针对某一个问题,在众多的限制条件下,如何去寻找一个最优解?可能大家想到了很多诸如“线性规划”,“动态规划” 这些经典 ...
- Matlab splinetx
function v = splinetx(x,y,u) %SPLINETX Textbook spline function. % v = splinetx(x,y,u) finds the pie ...
- ocp11g培训内部教材_053课堂笔记(043)_数据备份
053:数据库高级管理: 目录 第一部分:数据库备份与恢复... 4 第一章:备份恢复概述... 4 1.1 备份的意义: 4 1.2 数据库故障的类型:... 4 1.3 制定你的备份和恢复的计划. ...
- centos6.5 x86_64安装oracle 11.2.0.3grid
centos6.5 x86_64安装oracle 11.2.0.3grid 1.安装前的准备 工作 1.1.配置node1 1.1.1.配置虚拟机并安装centos 安装node1----- 1 ...
- 使用Json让Java和C#沟通的方法
原文:使用Json让Java和C#沟通的方法 最近很忙啊,新项目下来了,都没时间写博客了.频率降低点,但不能不总结跟大家分享啊. 我们在项目里经常要涉及到各模块间的通信,这其中又不可避免要碰到各类语言 ...