hdoj4906 Our happy ending(2014 Multi-University Training Contest 4)
对于一个定长(size = n)的数列a, 若其存在“位置相关”的子集(含空集)使得该子集所有元素之和为k,那么将数列a计数。
其中数列a中任一元素a[i]在[0, l]内自由取值。
数据条件0≤n, k ≤ 20, 0≤ l ≤ 1e9,计数结果对mod = 1e9 + 7取模。
无论直接计数还是考虑从反面计数都解决不了去重的问题,只能考虑dp。
枚举数列的长度i和压缩后的状态j,并且记录在该条件下的数列选取方案数dp[i][j]。
压缩后的状态j表示对于集合{1, 2, ..., min(l, k)}的选取情况。
其中集合中第i个元素在状态j中当且仅当j的二进制串的第i位为1。
显然我们有dp[0][0] = 1。
对于长度为p的数组,第p位可以选取的元素是0,1,2,...,l
考虑p位选取1,2,...,min(l, k)
那么对于数组长度为p-1时的任一状态j,在数组后追加元素i后的状态为:
j1 = j | ((j << i) & ((1 << k) - 1)) | (1 << (i - 1))
三部分分别表示原状态,原状态每个元素与元素i求和后增加的状态,i本身。
于是dp[p][j1] += dp[p - 1][j]。
而对于p位选取0或者大于min(l, k)的情形,j1 = j。
因此有dp[p][j] = (l - min(l, k)) * dp[p - 1][j]。
我们最后只需对dp[n][j],其中j第k位为1的累加即可。
由于数列每个元素非负,我们最后只关心那些集合存在和为k的子集,
而那些大于k的元素必然不是构成子集的元素,只有那些小于k的元素才对状态转移有用。
因此我们可以这样表示状态。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <set>
#include <cmath>
#include <ctime>
using namespace std;
#define lson (u << 1)
#define rson (u << 1 | 1)
typedef __int64 ll;
const int maxn = 1e6 + ;
const int maxm = ;
const ll mod = 1e9 + ; int n, l, k;
ll dp[( << ) + ];
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &n, &k, &l);
ll d = abs(l - k);
l = min(l, k);
int s = ( << k) - ;
memset(dp, , sizeof dp);
dp[] = ;
while(n--){
for(int j = s; j >= ; j--){
ll tem = dp[j];
if(!tem) continue;
for(int p = ; p <= l; p++){
int nex = ( << (p - )) | j | ((j << p) & s);
dp[nex] = (dp[nex] + tem) % mod;
}
dp[j] = (tem * ( + d)) % mod;
}
}
ll ans = ;
for(int i = s; i >= ; i--)
if(i & ( << (k - )))
ans = (ans + dp[i]) % mod;
printf("%I64d\n",ans);
}
return ;
}
hdoj4906 Our happy ending(2014 Multi-University Training Contest 4)的更多相关文章
- HDU4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)
Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- hdu 4946 2014 Multi-University Training Contest 8
Area of Mushroom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- 2014 Multi-University Training Contest 9#11
2014 Multi-University Training Contest 9#11 Killing MonstersTime Limit: 2000/1000 MS (Java/Others) ...
- 2014 Multi-University Training Contest 9#6
2014 Multi-University Training Contest 9#6 Fast Matrix CalculationTime Limit: 2000/1000 MS (Java/Oth ...
- 2014 Multi-University Training Contest 1/HDU4861_Couple doubi(数论/法)
解题报告 两人轮流取球,大的人赢,,, 贴官方题解,,,反正我看不懂.,,先留着理解 关于费马小定理 关于原根 找规律找到的,,,sad,,, 非常easy找到循环节为p-1,每个循环节中有一个非零的 ...
- 2014 Multi-University Training Contest 1/HDU4864_Task(贪心)
解题报告 题意,有n个机器.m个任务. 每一个机器至多能完毕一个任务.对于每一个机器,有一个最大执行时间Ti和等级Li,对于每一个任务,也有一个执行时间Tj和等级Lj.仅仅有当Ti>=Tj且Li ...
- 2016 Al-Baath University Training Camp Contest-1
2016 Al-Baath University Training Camp Contest-1 A题:http://codeforces.com/gym/101028/problem/A 题意:比赛 ...
- hdu 4937 2014 Multi-University Training Contest 7 1003
Lucky Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) T ...
- hdu 4941 2014 Multi-University Training Contest 7 1007
Magical Forest Time Limit: 24000/12000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
随机推荐
- LIS 最长递增子序列
一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...
- Redis Sets
Sets Sets 就是一个集合,集合的概念就是一堆不重复值的组合.利用Redis提供的Sets数据结构,可以存储一些集合性的数据,比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有 ...
- SQL 数据库 right join 和left join 的区别
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录inner join(等值连接) 只 ...
- hdu 4998
http://acm.hdu.edu.cn/showproblem.php?pid=4998 这道题,在比赛的时候看了很久,才明白题目的大意.都怪自己不好好学习英语.后来经过队友翻译才懂是什么意思. ...
- 利用并查集求最大生成树和最小生成树(nlogn)
hdu1233 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) T ...
- CSS禅意花园(设计一)
设计 1.排版样式. 正文部分文字比例比菜单不分班的大,可区分着两个区域(说明正文比菜单重要).排版也是一种交流方式,运用文字的大小.间距.颜色调整样式,给浏览者丰富的信息. 2.图标 3.分割线 适 ...
- [转]关于安装hadoop中出现的的 $HADOOP_HOME is deprecated 的解决方法
当前用户的.bash_profile在/home/用户/下,系统的.bash_profile在/etc/skel目录下; 默认可能是隐藏的:有人会问了,隐藏的我怎么打开它,一个简单的办法,直接使用vi ...
- c++的用处
C++准确说是一门中级语言,介于汇编和高级语言之间吧,要求程序员了解计算机的内部数据存储.个人认为,作为学生还是花功夫学C++,因为<设计模式><数据结构>这些课程基本上还是C ...
- HDU 4832 Chess(DP+组合数学)(2014年百度之星程序设计大赛 - 初赛(第二轮))
Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,“王”在棋盘上的走法遵循十字路 ...
- struts配置通配符*来匹配方法,实现动态调用
01:web.xml中配置,启动struts2 <?xml version="1.0" encoding="UTF-8"?> <web-app ...