传送门

题意

  将一个数N分解为2的幂之和共有几种分法?

题解

  定义dp[ i ]为 i 的分解方案数。

  初始化dp[0] = 2= 1;

  状态转移方程为:

  for i : 1 to N

    若 i 为偶数,则dp[ i ] = dp[ i / 2] + dp[i – 1] ;

    否则dp[i] = dp[ i – 1];

对状态转移方程的理解:

  打个表先~~~~

  i  i 的分解方案

  1......1

  2......1+1,2

  3......1+1+1,2+1

  4......(2+1+1),(1+1+1+1),(2+2),(4)

  5......2+1+1+1,1+1+1+1+1,2+2+1,4+1

  6......2+1+1+1+1,1+1+1+1+1+1,2+2+1+1,4+1+1,2+2+2,4+2

  7......(2+1+1+1+1+1),(1+1+1+1+1+1+1),(2+2+1+1+1),(4+1+1+1),(2+2+2),(4+2+1)

  8......(2+1+1+1+1+1+1),(1+1+1+1+1+1+1+1),(2+2+1+1+1+1),(4+1+1+1+1),(2+2+2),(4+2+1+1),(4+2+2),(2+2+2+2),(4+4),(8)

  以8的为例,dp[8]=dp[20+7]+dp[2* 4];

  8分解成2的幂之和,只能分解成2, 2, 2, 23之间的加和。

  如果分解方案中含有20,并且不能出现重复,那可以考虑7的分解方案中的每个方案都+1 <=> 8的含20的分解方案总数(对应表中橘色部分);

  因为dp[7]中的分解方案数是不重复的,所以每个方案数+1也是不重复的;

  那,如何使分解方案中不含有20呢?

  想一下4的分解方案数是怎么得到的?

  4分解成2的幂之,只能分解成2, 2, 22之间的加和;

  如果4中的每个方案都 ×2,那不就正好变成8的分解方案中只不含有20的分解方案了吗(对应表中蓝色部分)?

  如果 i 为奇数,就不能通过某数 ×2 来得到 i;

  那也就是说只能通过 (i-1) 方案中每个方案+1 得到 i 的所有分解方案,故dp[ i ]=dp[ i-1]

•Code

 #include<iostream>
#include<cstdio>
using namespace std;
const int MOD=1e9;
const int maxn=1e6+; int N;
int dp[maxn]; int main()
{
scanf("%d",&N);
dp[] = ; // 2^0
for(int i=;i <= N;++i)
{
if ((i & 0x1) == )//判断i是否为偶数
dp[i]=dp[ i / ]; //将i/2的每个构成数乘以2,得到 i
dp[i] += dp[i - ]; //将i-1的构成数拿过来加一
dp[i] %= MOD;
}
printf("%d\n",dp[N]);
return ;
}

分割线:2019.6.16

•类比“n的m划分”

重新理解了一下“n的m划分”这种题的求解方法,想到了这道题;

感觉这道题和n的m划分很像;

n的m划分在状态转移时考虑的是“划分数种是否包含0这个元素”;

而在此题中,考虑的是“是否包含20这个元素”;

这应该是有两者的性质决定的,前者需要的是任意数的累加,后者需要的是2的幂的累加;

而任意数中的最小值为0,2的幂的最小值为20=1;

根据最小值的不同,考虑的不包含的数也不同;

此题中,数 i 的划分可分为两类:

①包含20

②不包含20

包含 2很好办,直接将 i-1 的划分 +1 便可得到 i 的划分中包含 20 的划分方案数;

主要是不包含20要如何求解?

与n的m划分相仿,如果 i 为偶数,那么将 i/2 中划分 ×2 得到的就是 i 的划分不包含 20 的划分方案数;

根据上述讲解定义dp[ i ]表示 i 的划分方案数;

那么 dp[ i ]=dp[ i ]-1 + ( i为偶数 ? dp[ i/2 ] : 0);

dp[ 1 ] = 1;

Code

 #include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
const int maxn=1e6+;
const ll MOD=1e9; int n;
ll dp[maxn]; ll Solve()
{
dp[]=;
for(int i=;i <= n;++i)
{
dp[i]=dp[i-];
if(!(i&))
dp[i] += dp[i>>];
dp[i] %= MOD;
}
return dp[n]%MOD;
}
int main()
{
scanf("%d",&n);
printf("%lld\n",Solve());
return ;
}

poj 2229 Sumsets(记录结果再利用的DP)的更多相关文章

  1. NOIP 提高组 2014 飞扬的小鸟(记录结果再利用的DP)

    传送门 https://www.cnblogs.com/violet-acmer/p/9937201.html 参考资料: [1]:https://www.luogu.org/blog/xxzh242 ...

  2. poj 2385 Apple Catching(记录结果再利用的动态规划)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题意: 有两颗苹果树,在每一时刻只有其中一棵苹果树会掉苹果,而Bessie可以在很短的时 ...

  3. poj -2229 Sumsets (dp)

    http://poj.org/problem?id=2229 题意很简单就是给你一个数n,然后选2的整数幂之和去组成这个数.问你不同方案数之和是多少? n很大,所以输出后9位即可. dp[i] 表示组 ...

  4. 记录结果再利用的"动态规划"之背包问题

    参考<挑战程序设计竞赛>p51 https://www.cnblogs.com/Ymir-TaoMee/p/9419377.html 01背包问题 问题描述:有n个重量和价值分别为wi.v ...

  5. POJ 2229 Sumsets

    Sumsets Time Limit: 2000MS   Memory Limit: 200000K Total Submissions: 11892   Accepted: 4782 Descrip ...

  6. 记录结果再利用的"动态规划"

    2018-09-24 15:01:37 动态规划(DP: Dynamic Programming)是算法设计方法之一,在程序设计竞赛中经常被选作题材.在此,我们考察一些经典的DP问题,来看看DP究竟是 ...

  7. poj 2229 Sumsets(dp)

    Sumsets Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 400000/200000K (Java/Other) Total Sub ...

  8. poj 2229 Sumsets 完全背包求方案总数

    Sumsets Description Farmer John commanded his cows to search for different sets of numbers that sum ...

  9. POJ 2229 Sumsets(找规律,预处理)

    题目 参考了别人找的规律再理解 /* 8=1+1+1+1+1+1+1+1+1 1 8=1+1+1+1+1+1+1+2 2 3 8=1+1+1+1+2+2 8=1+1+1+1+4 4 5 8=1+1+2 ...

随机推荐

  1. git在实际开发中的应用

    PS: git操作实例(https://learngitbranching.js.org/?demo) 一, 创建分支,合并分支到master 1. 在远程仓库中创建master和test分支 2.本 ...

  2. vs code軟件操作

    https://www.imooc.com/article/39349 https://www.html.cn/archives/8144

  3. 自定义组件Component

    定义compa组件 由4个页面构成 compa.js: compa.json: compa.wxml: compa:wxss: 1.compa.json:在json文件进行自定义组件声明 { &quo ...

  4. 皮皮虾FAQ

    我们提供的软件,是市场上比较好操作的,如果有其他的软件也是可以使用我们的ip的 Windows 1.windows找不到粘贴的地方 window打开窗口后,请在屏幕右下角找小飞机,右键即可 2.win ...

  5. Subway POJ - 2502 最短路

    题意:给出地铁线  起点和 终点  坐地铁速度为v2  走路为v1 求起点到终点的最短距离  (答案需要四舍五入这里坑了好久) 拿给出的地铁站点 和起点终点建边即可  然后跑个迪杰斯特拉 #inclu ...

  6. 洛谷P5020货币系统

    题目 这个题打眼看上去可能是一个数论或者DP,其实我们可以简化一下题意,即 给定一个集合\(\alpha\),找到几个数使得这几个数可以拼凑起来这个集合里所有的数,且需要使这些数的个数最小. 这样这个 ...

  7. Android学习第6天

    创建一个新的activity 四大组件需要在清单文件中配置 可在清单文件中配置多个启动图标过单个启动图标 Activity下的lable和icon属性可以和Application节点的属性不一样,默认 ...

  8. Python可迭代对象中的添加和删除(add,append,pop,remove,insert)

    list: classmates = ['Michael', 'Bob', 'Tracy'] classmates.append('Adam') //添加在末尾,没有add()方法 classmate ...

  9. ansible 开源批量管理服务器工具

    Ansible 是一款基于 Python 开发的自动化运维工具,可以进行配置管理.批量部署等功能.对于机器较多的场景,可以使用 Ansible 来免去重复敲命令的烦恼. 安装ansibleyum -y ...

  10. 【CF981D】Bookshelves(贪心,动态规划)

    [CF981D]Bookshelves(贪心,动态规划) 题面 洛谷 Codeforces 给定一个长度为\(n\)的数列,把他们划分成\(k\)段,使得每段的和的结构按位与起来最大. 题解 从高位往 ...