Codechef APRIL14 ANUCBC Cards, bags and coins 背包DP变形
题目大意
有n个数字,选出一个子集,有q个询问,求子集和模m等于0的方案数%1000000009。(n <= 100000,m <= 100,q <= 30)
假设数据很小,我们完全可以做一个背包。
我们沿着背包的思路,看能不能给物品分一下类,由于m比较小,完全按N个数字模M后的值进行分类,这样就变成了一个多重背包的问题。(转移时要乘上一个组合数)
这时候的时间复杂度是n*m,还是不能过。
对于DP时所枚举到的模m后余数j,它所进行的状态转移是一定的,如果把这些转移先预处理出来,时间复杂度就能得到有效减小。
分析一下,转移方程是 F[i][j] = sigma(F[i][(j-i*k+m)%m]*C(count[i], k))%MOD,可以发现,(j-i*k+m)%m的值最多也只有m个,根本不需要枚举count[i]个这么多。
设t = (i*k)%m,G[i][t] = sigma(C(count[i], k)) (k = 0..count[i] 且 i*k%m == t),G数组可以在O(n)的时间内预处理出来。
新的转移方程就可以整理为 F[i][j] = sigma(F[i][(j-t+m)%m]*G[i][t])%MOD。 总的时间复杂度为O(n+m^3)。
问题还没有结束,G数组的计算也需要一定的技巧。如果计算每个G[i][t]的值都算一次逆元和组合数,时间复杂度起码要加上一个log,会TLE。
仔细分析可以发现,所计算的组合数C(count[i], k) (k = 0..count[i]),k是严格递增的,设temp = C(count[i], k-1),则C(count[i], k) = temp*(count[i]-(k-1))*inv[k]。
inv数组可以利用逆元打表O(n)的方法来实现,具体可参考博文:http://blog.csdn.net/guhaiteng/article/details/52123385
程序对拍过,但运行速度较慢。
#include <cstdio>
#include <cstring> using namespace std; typedef long long LL;
const int maxn = ;
const int MOD = ;
int n, m, Q;
int ccount[];
LL g[][], inv[maxn], f[][];
int a[maxn], ans; void add(LL &x, LL y)
{
x += y;
if (x >= MOD)
x -= MOD;
} void prepare()
{
for (int i = ; i < m; ++i)
ccount[i] = ;
for (int i = ; i <= n; ++i)
{
int temp = (a[i]%m+m)%m;
ccount[temp] ++;
}
for (int i = ; i < m; ++i)
for (int j = ; j < m; ++j)
g[i][j] = ;
for (int i = ; i < m; ++i)
{
LL temp = ccount[i];
add(g[i][], );
add(g[i][i%m], ccount[i]);
for (int j = ; j <= ccount[i]; ++j)
{
(temp *= (ccount[i]-(j-))) %= MOD;
(temp *= inv[j]) %= MOD;
add(g[i][(i*j)%m], temp);
}
}
} void dp()
{
memset(f, , sizeof(f));
f[][] = g[][];
for (int i = ; i < m; ++i)
for (int j = ; j < m; ++j)
for (int k = ; k < m; ++k)
{
LL temp = f[i-][(j-k+m)%m]*g[i][k]%MOD;
add(f[i][j], temp);
}
ans = f[m-][];
} int main()
{
inv[] = ;
for (int i = ; i <= ; ++i)
inv[i] = LL(MOD-MOD/i)*inv[MOD%i]%MOD;
int Task;
scanf("%d", &Task);
while (Task --)
{
scanf("%d %d", &n, &Q);
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]);
while (Q --)
{
scanf("%d", &m);
prepare();
dp();
printf("%d\n", ans);
}
}
return ;
}
Codechef APRIL14 ANUCBC Cards, bags and coins 背包DP变形的更多相关文章
- [CC-ANUCBC]Cards, bags and coins
[CC-ANUCBC]Cards, bags and coins 题目大意: 给你\(n(n\le10^5)\)个数,\(q(q\le30)\)次询问,问从中选取若干个数使得这些数之和为\(m(m\l ...
- BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )
题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...
- CodeChef Cards, bags and coins [DP 泛型背包]
https://www.codechef.com/problems/ANUCBC n个数字,选出其一个子集.求有多少子集满足其中数字之和是m的倍数.n $\le$ 100000,m $\le$ 100 ...
- SGU 415. Necessary Coins ( 背包dp )
题意大概是:给出N个硬币, 面值为a_i, 问要凑成X元哪些硬币是不可或缺的.1 ≤ N ≤ 200, 1 ≤ x ≤ 10^4 直接枚举, 然后就是01背包了. 为了不让复杂度多乘个N, 我们就从左 ...
- Robberies (01背包dp变形)
题意:一个强盗要抢劫银行又不想被抓到,所以要进行概率分析求他在不被抓的情况下能抢最多的钱.他给定T(样例个数),N(要抢的银行的个数),P(被抓的概率要小于P)Mj(强盗能抢第j个银行Mj元钱),Pj ...
- PAT甲题题解-1068. Find More Coins (30)-dp,01背包
一开始没多想,虽然注意到数据N<=10^4的范围,想PAT的应该不会超时吧,就理所当然地用dfs做了,结果最后一组真的超时了.剪枝啥的还是过不了,就意识到肯定不是用dfs做了.直到看到别人说用0 ...
- Codeforces Round #207 (Div. 1) D - Bags and Coins 构造 + bitset优化dp + 分段查找优化空间
D - Bags and Coins 思路:我们可以这样构造,最大的那个肯定是作为以一个树根,所以我们只要找到一个序列a1 + a2 + a3 .... + ak 并且ak为 所有点中最大的那个,那么 ...
- UVA 562 Dividing coins --01背包的变形
01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostre ...
- 【BZOJ1004】【HNOI2008】Cards 群论 置换 burnside引理 背包DP
题目描述 有\(n\)张卡牌,要求你给这些卡牌染上RGB三种颜色,\(r\)张红色,\(g\)张绿色,\(b\)张蓝色. 还有\(m\)种洗牌方法,每种洗牌方法是一种置换.保证任意多次洗牌都可用这\( ...
随机推荐
- zepto.js 实现原理解析
zepto 是移动端常用的 dom 库,代码轻巧,操作方式类同 jquery.那么 zepto 的核心实现原理是什么呢?
- hdu 2063 过山车 二分匹配(匈牙利算法)
简单题hdu2063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063 过山车 Time Limit: 1000/1000 MS (Java/Ot ...
- offset宏的讲解【转】
转自:http://blog.csdn.net/tigerjibo/article/details/8299584 1.offset宏讲解 #define offsetof(TYPE, MEMBER) ...
- How to insert a segment of noise to music file
如何向音频文件中插入噪声 为了研究噪声和音乐对EEG的的影响,实验前需要准备一段夹杂噪声的音乐. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...
- 转:PHP环境搭建 - Linux
本文PHP环境采用,nginx + PHP7 + mysql 5.6 一.安装mysql 5.6 参见:http://www.cnblogs.com/rslai/p/7853465.html 二.Ng ...
- HDU 4725 The Shortest Path in Nya Graph(spfa+虚拟点建图)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4725 题目大意:有n层,n个点分布在这些层上,相邻层的点是可以联通的且距离为c,还有额外给出了m个条边 ...
- Sublime Text 2之Emmet插件安装及使用
1.安装Emmet How To Install?Reffer to this link:http://www.ituring.com.cn/article/47310 2.使用Emmet--Abbr ...
- Python 3.6安装教程
0x01 安装Python 1.1 说明 目前,Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的. 本教程安装的是python-3.6.1-amd64版本. Python官 ...
- jquery文档
http://jquery.cuishifeng.cn/selected_1.html
- WPF 获取计算机字体
//加载计算机上可用的字体 public void LoadFonts(object ietfLanguageTag) { try { var sysFonts = Fonts.SystemFontF ...