题意:

  Given a sequence a_1,a_2,...,a_n, if we can take some of them(each a_i can only be used once), and they sum to k, then we say this sequence is a good sequence.
   How many good sequence are there? Given that each a_i is an integer and 0<= a_i <= L.

  给你一个序列: a_1, a_2, ..., a_n,如果我们能够取出他们中的一些(每个a_i只能取一次),并且他们的和是k,我们就把这个序列称为一个好的序列。

  如果每个a_i都是0到L中的整数,那么他们一共能组成多少好序列呢?

思路:

  状态压缩。

  dp[i][S]表示长度为i的序列,能组合成的加和的集合为S的情况有多少种(集合用数字的位来表示,1表示可以组成,0表示不可以。因为有用的数字最多只有20,所以可以这样表示)。

  这样,我们可以枚举第i+1位,得到一个新的可以组成的数的集合。原理和背包类似。 在和别人的讨论中发现,用位运算可以很方便的表示这个背包的内容,我们假设原本可以组成的集合为S,现在枚举放不放进背包的数是j。那么,不放进背包的时候可能组成的集合还是S;而放进背包的话,可能组成的集合就变成了(S<<j);所以枚举j可能组成的所有集合就是 S|(S<<j) 看起来是不是很简洁。

  所以这样,我们的转移方程就可以写成 dp[i+1][S] = sum{dp[i][S0] | (S0|(S0<<j) ) == S}

  值得注意的是,直接开 n*2^n 的数组可能会爆内存,观察转移是一层一层的进行的,所以我们可以用滚动数组进行优化。

(最后,感谢alpc同学的耐心讲解 :)

代码:(这样做会跑2秒,真心不知道那些0毫秒的怎么做的Orz)

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <time.h> using namespace std; typedef __int64 ll; const int INF = <<;
const int MAXN = ;
const ll MOD = (ll) 1e9+; ll dp[<<MAXN];
int n, k, L; void solve() {
memset(dp, , sizeof(dp));
int MIN = min(L, k);
int FULL = (<<(k+))-; //全集 dp[] = ;
for (int i = ; i < n; i++) {
for (int S = FULL; S > ; S--) if (dp[S]>) {
ll tmp = dp[S];
for (int j = ; j <= MIN; j++) //枚举每一个有效数字
dp[FULL&(S|(S<<j))] = (dp[FULL&(S|(S<<j))]+tmp)%MOD;
if (MIN<L)
dp[S] = (dp[S]+((L-MIN)*tmp)%MOD)%MOD;
}
} ll ans = ;
for (int S = ; S <= FULL; S++) if (S&(<<(k)))
ans = (ans+dp[S])%MOD; printf("%I64d\n", ans);
} int main() {
#ifdef Phantom01
freopen("HDU4906.txt", "r", stdin);
#endif //Phantom01 int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d%d", &n, &k, &L);
solve();
} return ;
}

HDU 4906 Our happy ending的更多相关文章

  1. HDU 4906 Our happy ending (状压DP)

    HDU 4906 Our happy ending pid=4906" style="">题目链接 题意:给定n个数字,每一个数字能够是0-l,要选当中一些数字.然 ...

  2. HDU 4906 Our happy ending(2014 Multi-University Training Contest 4)

    题意:构造出n个数 这n个数取值范围0-L,这n个数中存在取一些数之和等于k,则这样称为一种方法.给定n,k,L,求方案数. 思路:装压 每位 第1为表示这种方案能不能构成1(1表示能0表示不能)   ...

  3. HDU 4906 状态压缩dp

    Our happy ending Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  4. hdu 4906 3-idiots fft

    题目链接 n个火柴棍取3个, 问能组成三角形的概率是多少. kuangbin大神的博客写的很详细了..http://www.cnblogs.com/kuangbin/archive/2013/07/2 ...

  5. HDU 4906 (dp胡乱搞)

    The Romantic Her Problem Description There is an old country and the king fell in love with a devil. ...

  6. HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  7. hdu 1086(计算几何入门题——计算线段交点个数)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1086 You can Solve a Geometry Problem too Time Limit: 2 ...

  8. hdu 5154 Harry and Magical Computer

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5154 Harry and Magical Computer Description In reward ...

  9. hdu 1038 Biker&#39;s Trip Odometer(水题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=1038 Biker's Trip Odometer Time Limit: 2000/1000 MS ...

随机推荐

  1. R和中心度、中心势

    最近用R画论文里的弦图,恰好借的书里着重写了中心度等问题. 网上流行一套密歇根大学社交计算的教程.但是前两年看了好几遍总是搞不清,即便是记公式也是收效不大.不妨按照书上总结一下. 绝对法: 无向图点度 ...

  2. Codeforces 982 B. Bus of Characters(模拟一个栈)

    解题思路: 排序之后模拟一个栈(也可以用真的栈),时间复杂度o(n). 代码: #include <bits/stdc++.h> using namespace std; typedef ...

  3. 一个PHPer如何深入学习ES搜索引擎?

    公司早在一年前就上ES作为后端搜索服务的项目 ,我们PHPer只是负责实现业务接口,es的一些查询,优化技巧由另一组同事(JAVAer)负责,有时,一个需求过来,改动较大时,需要更改查询json语句, ...

  4. 高阶函数-lambda表达式

    #2.6 map()# 第一个参数传入一个函数,,第二个参数为一个可迭代对象li_1 = (1,3,5,7)def funcA(x): return x*xm1 = map(funcA,li_1)pr ...

  5. 异步线程编程,线程池,线程组,后面涉及ThreadLocal在理解

    join模拟订单 package com.future.demo.future; /** * * * @author Administrator * */ public class NormalThr ...

  6. CentOS 7在grub rescue模式中修复系统

    安装完CentOS 7后 修改硬盘分区后,系统重启后,无法正常启动,进入grub rescue模式: 网上大多数centos grub rescue的资料应该是Centos 7之前的,其中提到的命令很 ...

  7. C语言数组和指针是不同的

    有一个这样的错误: 在一个文件中定义:int mango[100];  在另一个文件中声明:extern int *mango;  将会产生错误 定义和声明的区别: 在C中,任何对象都有且只有一个定义 ...

  8. 紫书 习题 8-22 UVa 1622 (构造法)

    这道题的构造法真的复杂--要推一堆公式--这道题写了几天了--还是没写出来-- 一开始简单的觉得先左右来回, 然后上下来回, 然后把剩下的执行完了好了, 然后就WA. 然后换了个思路, 觉得是贪心, ...

  9. cocos2d_android 第一个游戏

    依据上一篇文章.创建好cocos2d--android的开发环境 先上效果图 实现该效果的代码: package com.cn.firstgame; import org.cocos2d.layers ...

  10. OC第二课

    主要内容:实例变量可见度.方法 一.实例变量可见度 public(共同拥有的):实例变量能够在类的内部和外部使用 protected(受保护的.默认的):实例变量仅仅能在该类及其子类中使用 priva ...