传送门

题意

  将一个数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. github & markdown & collapse & table

    github & markdown collapse & table https://github.com/Microsoft/TypeScript/issues/30034 GitH ...

  2. Mybatis之collection嵌套查询mapper文件写法

    mapper.xml写法举例 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper ...

  3. 排列组合n选m算法

    找10组合算法,非递归 http://blog.csdn.net/sdhongjun/article/details/51475302

  4. codeforces527D

    Clique Problem CodeForces - 527D 所谓图的极大团是指在一个无向图中找到最多的点,使得这些点构成的图(即导出子图)是一个完全图,然而这个问题至今没有有效的多项式解法,当然 ...

  5. 李昊大佬的CV模板

    #include<cstdio> #include<iostream> #include<cstdlib> #include<iomanip> #inc ...

  6. 用二分法定义平方根函数(Bisection method Square Root Python)

    Python里面有内置(Built-in)的平方根函数:sqrt(),可以方便计算正数的平方根.那么,如果要自己定义一个sqrt函数,该怎么解决呢? 解决思路:  1. 大于等于1的正数n的方根,范围 ...

  7. Python中操作ini配置文件

    这篇博客我主要想总结一下python中的ini文件的使用,最近在写python操作mysql数据库,那么作为测试人员测试的环境包括(测试环境,UAT环境,生产环境)每次需要连接数据库的ip,端口,都会 ...

  8. codeforces553C Love Triangles

    题目链接:codeforces553C Love Triangles 我们来看一下对于一个合法三角形可能出现的边 我们发现,在确定了两边之后,第三条边是什么也就随之确定了 我们用\(1\)表示\(lo ...

  9. 【转载】docker 应用之动态扩展容器空间大小

    docker 容器默认的空间是 10G, 如果想指定默认容器的大小(在启动容器的时候指定),可以在 docker 配置文件里通过 dm.basesize 参数指定,比如 docker -d --sto ...

  10. 【CF446C】DZY Loves Fibonacci Numbers (线段树 + 斐波那契数列)

    Description ​ 看题戳我 给你一个序列,要求支持区间加斐波那契数列和区间求和.\(~n \leq 3 \times 10 ^ 5, ~fib_1 = fib_2 = 1~\). Solut ...