UVa 1213 (01背包变形) Sum of Different Primes

题意:

选择K个质数使它们的和为N,求总的方案数。

分析:

虽然知道推出来了转移方程, 但还是没把代码敲出来,可能基本功还是不够吧。

d(i, j)表示i个素数的和为j的方案数,则 d(i, j) = sigma d(i-1, j-p[k]) ,其中p[k]表示第k个素数

注意递推的顺序是倒着推的,否则会计算重复的情况。

代码中第二重和第三重循环的顺序可互换。

 1 #include <cstdio>
 2 #include <cmath>
 3
 4 const int maxp = 190;
 5 const int maxn = 1120;
 6 int cnt = 0;
 7 int prime[maxp];
 8 bool vis[maxn + 10];
 9
10 int d[15][maxn + 10];
11
12 void Init()
13 {
14     int m = sqrt(maxn + 0.5);
15     for(int i = 2; i <= m; ++i) if(!vis[i])
16         for(int j = i * i; j <= maxn; j += i) vis[j] = true;
17     for(int i = 2; i <= maxn; ++i) if(!vis[i]) prime[cnt++] = i;
18 }
19
20 void dp()
21 {
22     d[0][0] = 1;
23     for(int i = 0; i < cnt; ++i)
24         for(int j = 14; j > 0; --j) //j个质数的和
25             for(int k = maxn; k >= prime[i]; --k) //为k
26                 d[j][k] += d[j-1][k-prime[i]];
27 }
28
29 int main()
30 {
31     //freopen("in.txt", "r", stdin);
32     Init();
33     dp();
34     int k, n;
35     while(scanf("%d%d", &n, &k) == 2 && n) printf("%d\n", d[k][n]);
36
37     return 0;
38 }

代码君

时间: 2024-08-19 14:33:42

UVa 1213 (01背包变形) Sum of Different Primes的相关文章

HDU 2955 Robberies --01背包变形

这题有些巧妙,看了别人的题解才知道做的. 因为按常规思路的话,背包容量为浮点数,,不好存储,且不能直接相加,所以换一种思路,将背包容量与价值互换,即令各银行总值为背包容量,逃跑概率(1-P)为价值,即转化为01背包问题. 此时dp[v]表示抢劫到v块钱成功逃跑的概率,概率相乘. 最后从大到小枚举v,找出概率大于逃跑概率的最大v值,即为最大抢劫的金额. 代码: #include <iostream> #include <cstdio> #include <cstring>

Wikioi 1025 01背包变形

这题多加了菜品必选编号,所以刚开始不知道怎么写,原来就把必选的处理下就行了,因为有重复,但是相同的价值与价格都一样,所以这里就直接挑出来就行了. 把不是必选的在里面用dp即可,dp之前也要把重复的舍去. 因为总价格容量为浮点数,所以先乘以10变成整数就可以用01背包了. #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <deque&

POJ 3093 Margaritas on the River Walk (0-1背包变形)

这题目的思路很巧妙,什么情况下剩下的所有物品都放不下呢?就是当前剩余物品中最小的那个也放不下.所以,先把物品按照容量从小到大排序,依次枚举当前背包为放不下的最小物品的情况. 对于当前物品i,必有1到i-1的所有物品都放进去,这时候比i大的物品谁放谁不放是不确定的.转换成0-1背包问题:把前i-1个物品都放进去以后,得到空间为tsum - sum[i-1](前缀和)的包,只要从第i+1到第n个物品中拿出一个方案填充这个包使得剩余体积小于第i个物品的体积就可以了,把总方案数累加就是结果! 注意特殊情

codeforce Gym 101102A Coins (01背包变形)

01背包变形,注意dp过程的时候就需要取膜,否则会出错. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXW 15005 #define N 155 #define LL long long #define MOD 1000000007 int w1[N],w2[N]; LL dp1[MAXW],dp2[MAXW]; int main(

codeforces 742D Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses ——(01背包变形)

题意:给你若干个集合,每个集合内的物品要么选任意一个,要么所有都选,求最后在背包能容纳的范围下最大的价值. 分析:对于每个并查集,从上到下滚动维护即可,其实就是一个01背包= =. 代码如下: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <vector> 5 using namespace std; 6 const int N = 1000 + 5;

HDU 2639 Bone Collector II(01背包变形【第K大最优解】)

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4739    Accepted Submission(s): 2470 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took pa

UVA 12563 Jin Ge Jin Qu hao 01背包变形

基本的01背包,更新的时候保持背包里每一个元素的num最大然后time尽量长 CSDN也支持makedown了试一下 12563 Jin Ge Jin Qu hao (If you smiled when you see the title, this problem is for you ^_^) For those who don't know KTV, see: http://en.wikipedia.org/wiki/Karaoke_box There is one very popul

uva 12563(动态规划起步第三天 01背包变形)

谈到背包,大家肯定都熟悉,我就不多讲,而这题挺有意思.DP[i][j] 表示前 i 首歌在j时间内唱的最多曲目: 状态有了,那么怎么转移呢? DP[i][j] = max{DP[i - 1][j],DP[i - 1][j - t[i]] + 1}; 但是此题还有时间.所以如果初始化为0的话,按照平常背包的代码,很难求出最长时间. 所以我们初始化为-1,且-1时不计算,那么这就避免了01背包的情况: 是不是觉得很像01背包的恰好装满情况.对,当然可以初始化为-无穷: 1 #include <ios

soj 2222 01背包变形

背景:wa~Tl~看来背包还是很欠缺啊~ 思路1(1500ms):变形的01背包.把题目改为:选择一组HP和大于等于所需血量且这组物品的分数之和最小,即可.这里把HP看做cost,score看做weight.但是这个题有个特点是最后选择HP必须大于等于k,容易想到,最多我们会有k+10000(10000为单个物品的最大HP值)的HP值,所以我们有这样的转移方程: for i 0....n for j K+10000....cost[i] F[j]=min(F[j],F[j-cost[i]]+we