对于这个问题, 我们显然可以看出来, 当他是奇数的时候, 直接等于他的前一个偶数  

    dp [ i ] = dp [ i - 1] ;

    那么问题, 当它是偶数的时候, 我们应该怎么进行 dp 记忆化搜索并且递归?  

  不知你是否记得化分数问题, 不记得话,请看dp初级内容, 就在DP 内容

  我们这里也是同样采取分成组内部有 1, 和分成组的内部没有 1

    当有一的时候, 那么就和上面的奇数一样, 具体说一下为什么, 以为它是偶数,一旦他有一, 那么至少为 2 个, 我们把这两个 1 进行合并, 然后看成  i - 1 中剩下的 一个 1 ,完成了递归

    当没有一的时候, 我们可以直接 除以二进行处理, 以为最小化单元就可以看做之前的最小化单元 1 ,

  所以说  dp [ i ]  =  dp [ i - 1] + dp [ i / 2 ] ;

    下面是代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <list>
#include <map>
#include <stack>
#include <set>
using namespace std;
const int MAX_N = ;
const int MOD = ;
int dp[MAX_N];
// TM 递归会栈溢出, 这也太狗了吧!!
int rec(int n){
if(dp[n] != -) return dp[n];
else{
if(n & ) //奇数
dp[n] = rec(n - );
else{
dp[n] = (rec(n - ) + rec(n >> )) % MOD;
}
}
return dp[n];
} int main()
{
int n;
memset(dp, , sizeof(dp)); dp[] = ; dp[] = dp[] = ;
cin>>n;
for(int i = ; i <= n; i++){
dp[i] = dp[i - ];
if(!(i & )){
dp[i] += dp[i>>];
}
dp[i] %= MOD;
}
printf("%d\n", dp[n]);
return ;
}

除了这一种写法还会有另外一种的写法:

这个方法类似于背包

然后就是原来的基础上进行加上了新的  2  的倍数!

#include<iostream>
#include<cstdio>
using namespace std;
const int mod = 1e9;
const int maxn = ; int main(){
int c[] = {};
long long int dp[maxn] = {};
for(int i = ; i < ; i++)
c[i] = c[i-] * ;
dp[] = ;
int n;
cin >> n;
for(int i = ; i < ; i++){
for(int j = c[i];j < n+; j++){
//当他循环的时候, 相当于 在最大 为 c[i] 因子的限制条件下, 他的种类数目
dp[j] = dp[j] + dp[j-c[i]];
// 这个递归关系是相当于有了一个甚至多个 c[i] 的时候, 进行递归, 然后加上之前没有的
if(dp[j] > mod) dp[j] = dp[j] % mod;
}
}
printf("%lld\n", dp[n]);
return ;
}

但是图片中有点小错误, 不知道你发现了没有, 应该是: dp [ i ] [ j ]  = dp [ i - 1 ] [ j ]   + dp [ i  ] [  j - w [ i ] ]   !!!

所以说, 上代码 :

#include <iostream>
#include <cstdio>
#include <algorithm>
#define Maxn 1000005
using namespace std;
int n;
int w[Maxn];
int cnt=;
int dp[Maxn];
int main()
{
scanf("%d",&n);
for(int i=;(<<i)<=n;i++)//构造所有物品
w[cnt++]=(<<i);
dp[]=;
for(int i=;i<cnt;i++)
for(int j=w[i];j<=n;j++)
dp[j]=(dp[j]+dp[j-w[i]])%;//取余 printf("%d\n",dp[n]);
return ;
}

高深的dp POJ 2229Sumsets的更多相关文章

  1. 状压DP POJ 3254 Corn Fields

    题目传送门 /* 状态压缩DP:先处理硬性条件即不能种植的,然后处理左右不相邻的, 接着就是相邻两行查询所有可行的种数并累加 写错一个地方差错N久:) 详细解释:http://www.tuicool. ...

  2. 状压DP POJ 2411 Mondriaan'sDream

    题目传送门 /* 题意:一个h*w的矩阵(1<=h,w<=11),只能放1*2的模块,问完全覆盖的不同放发有多少种? 状态压缩DP第一道:dp[i][j] 代表第i行的j状态下的种数(状态 ...

  3. dp poj 1080 Human Gene Functions

    题目链接: http://poj.org/problem?id=1080 题目大意: 给两个由A.C.T.G四个字符组成的字符串,可以在两串中加入-,使得两串长度相等. 每两个字符匹配时都有个值,求怎 ...

  4. 图论+dp poj 1112 Team Them Up!

    题目链接: http://poj.org/problem?id=1112 题目大意: 有编号为1~n的n个人,给出每个人认识的人的编号,注意A认识B,B不一定认识A,让你将所有的人分成两组,要求每组的 ...

  5. Treats for the Cows 区间DP POJ 3186

    题目来源:http://poj.org/problem?id=3186 (http://www.fjutacm.com/Problem.jsp?pid=1389) /** 题目意思: 约翰经常给产奶量 ...

  6. DFS(DP)---POJ 1014(Dividing)

    原题目:http://poj.org/problem?id=1014 题目大意: 有分别价值为1,2,3,4,5,6的6种物品,输入6个数字,表示相应价值的物品的数量,问一下能不能将物品分成两份,是两 ...

  7. 区间DP POJ 1141 Brackets Sequence

    Brackets Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29520   Accepted: 840 ...

  8. 矩阵快速幂+概率DP poj 3744

    题意:在一条不满地雷的路上,你现在的起点在1处.在N个点处布有地雷,1<=N<=10.地雷点的坐标范围:[1,100000000]. 每次前进p的概率前进一步,1-p的概率前进1-p步.问 ...

  9. 区间DP poj 2955

    求最多有几个括号可以匹配 #include<stdio.h> #include<string.h> #include<algorithm> using namesp ...

随机推荐

  1. [shell]如何测试shell脚本,保证正确

    如何用最快最有效的方式进行测试? 很多开发的习惯是,二话不说,写完/拿到,就跑一把,看看输入,输出,想要的操作是否完成,也就过了. 其实这是十分不严谨的,若是未经过QA,风险还是相当大的. 以下即sh ...

  2. Eclipse修改为中文版

    1.打开浏览器访问 https://www.eclipse.org/babel/downloads.php 复制语言包的url地址,我选择最新的 2.打开eclipse,依次选择菜单栏“Help - ...

  3. pwn学习日记Day21 《程序员的自我修养》读书笔记

    Linux内核装载ELF过程 (1)bash进程调用fork()系统调用创建一个新的进程 (2)新的进程调用execve()系统调用执行指定的ELF文件,原先的bash进程继续返回等待刚才启动的新进程 ...

  4. wan口的ip是干什么用的

    wan口的ip是外网的ip,属于公网的ip.主要用于外网的识别,WAN口主要用于连接外部网络,如ADSL.DDN.以太网等各种接入线路:而LAN口用来连接家庭内部网络,主要与家庭网络中的交换机.集线器 ...

  5. set serveroutput on

    使用set serveroutput on 命令设置环境变量serveroutput为打开状态,从而使得pl/sql程序能够在SQL*plus中输出结果 使用函数dbms_output.put_lin ...

  6. test20190510

  7. Java的三种工厂模式

    一.简单工厂模式 简单工厂的定义:提供一个创建对象实例的功能,而无须关心其具体实现.被创建实例的类型可以是接口.抽象类,也可以是具体的类 实现汽车接口 //产品接口 //汽车需要满足一定的标准 pub ...

  8. C++数据结构之排序

    一.简单排序 冒泡排序: 插入排序: 逆序对 希尔排序:

  9. 同一个电脑配置两个github账号

    mac中.ssh文件夹在根目录下,所以表示成 ~/.ssh/. 一.同一个电脑配置两个github账号1.分别为两个GitHub账号生成SSH密钥 $ cd ~/.ssh $ ssh-keygen - ...

  10. Run Hyper-V and VirtualBox on the same machine (轉載)

    Run Hyper-V and VirtualBox on the same machine Posted on September 5, 2012 by derek gusoff Recently ...