数的集合问题

  题目大意:给定你一个整数m,你只能用2的k次幂来组合这个数,问你有多少种组合方式?

  这一题一看,天啦太简单了,完全背包?是不是?

  不过的确这一题可以用完全背包来想,但是交题绝对是TLE,如果真的是完全背包的做法那我就不用等那么多天再发这个坑,这一题的确要用到点奇妙的思想。

  首先,我们忽略了这一题的最重要的一个条件,我们使用的数就是2次幂的,那么2次幂的数可以做什么呢?这就是一个数学问题了

  不过不要怕,这个数学问题也很好想,

    首先:任何一个奇数一定有1来组成,推论:任何偶数都可以只由除了1的数组成

    其次,任何一个偶数都可以由一个数左移1来得到(参考二进制)

  下面我们就用这两个数学结论来思考怎么简化递推。

  回到问题上来,完全背包会TLE的原因是出在在第二个循环的时候对j进行了过多的枚举,那么我们在用这两个结论的时候必须避开这一点,最好一步到位,所以我们必须把个数全部压在前一次的情况上,那么我们可首先用结论1,对于任何一个奇数,我们都可以用上一个偶数+1(组合数不变,因为只能加这个1),且这个集合不能由其他集合直接得到,那么我们就得到第一个递推公式

   dp[j]=dp[j-1]  当j=奇数

  现在用到第二个结论,因为我们的偶数可以从奇数得到,也可以从偶数得到,那么可以第一部分可以从dp[j-1]得到,另外一个部分就要思考结论2,因为我们只是左移,组合数是不变的,所以我们还可以从dp[j>>1]中得到另一部分的组合数,这样就避开了一个一个查找枚举i的背包了

  所以综上,状态转移方程为:

    dp[i]=dp[i-1]  当i是奇数

    dp[i]=dp[i-1]+dp[i>>1]  当i是偶数  

    (注意这一题只显示9个数字)

 #include <stdio.h>
#include <stdlib.h>
#define M 1000000000 long long Combinatories[]; int main(void)//这一题不能用完全背包,会超时
{
int N, i;
Combinatories[] = ;//这个地方要设置成1 for (i = ; i < ; i++)
{
if (i % == )
Combinatories[i] = Combinatories[i - ];
else
Combinatories[i] = Combinatories[i - ] + Combinatories[i >> ];
Combinatories[i] %= M;
} while (~scanf("%d", &N))
printf("%d\n", Combinatories[N] % M); return ;
}

DP:Sumsets(POJ 2229)的更多相关文章

  1. poj 2229 【完全背包dp】【递推dp】

    poj 2229 Sumsets Time Limit: 2000MS   Memory Limit: 200000K Total Submissions: 21281   Accepted: 828 ...

  2. poj -2229 Sumsets (dp)

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

  3. Sumsets(POJ 2229 DP)

    Sumsets Time Limit: 2000MS   Memory Limit: 200000K Total Submissions: 15293   Accepted: 6073 Descrip ...

  4. poj 2229 Sumsets(dp)

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

  5. poj 2229 Sumsets(dp 或 数学)

    Description Farmer John commanded his cows to search . Here are the possible sets of numbers that su ...

  6. poj 2229 Sumsets(记录结果再利用的DP)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题意: 将一个数N分解为2的幂之和共有几种分法? 题解: 定义dp[ i ]为数 i 的 ...

  7. POJ 2229 Sumsets【DP】

    题意:把n拆分为2的幂相加的形式,问有多少种拆分方法. 分析:dp,任何dp一定要注意各个状态来源不能有重复情况.根据奇偶分两种情况,如果n是奇数则与n-1的情况相同.如果n是偶数则还可以分为两种情况 ...

  8. poj 2229 Sumsets DP

    题意:给定一个整数N (1<= N <= 1000000),求出以 N为和 的式子有多少个,式子中的加数只能有2的幂次方组成 如5 : 1+1+1+1+1.1+1+1+2.1+2+2.1+ ...

  9. POJ 2229 Sumsets

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

随机推荐

  1. JEECMS页面中常用标签

    (1)在段落前给每一行加序号 从0开始:${a_index}从1开始:${a_index+1} (2)标记说明 [文章导航]:[@cms.Position /] [文章标题]:${arti.title ...

  2. MySQL tips (日期时间操作/concat 等)

    1.  Query结尾要加一个分号: 2.  数据库和表 SHOW DATABASES;    USE YOUR_DB; SHOW TABLES; SHOW COLUMNS FROM study或者D ...

  3. Android APK反编译问题

    因为这几天想做一个离线音乐播放器,然后需要很多.png图片,在度娘上搜图片感觉效果不好, 就需要用到反编译工具来将一些.apk文件中的资源文件提取出来. 这里就只讲下怎么使用工具来进行反编译,什么?你 ...

  4. javaweb学习总结(二十九)——EL表达式

    一.EL表达式简介 EL 全名为Expression Language.EL主要作用: 1.获取数据 EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象.获取数 ...

  5. udf提权方法和出现问题汇总

    一.适用条件 1.目标系统是Windows(Win2000,XP,Win2003): 2.你已经拥有MYSQL的某个用户账号,此账号必须有对mysql的insert和delete权限以创建和抛弃函数( ...

  6. 如何快速读懂大型C++程序代码

    要搞清楚别人的代码,首先,你要了解代码涉及的领域知识,这是最重要的,不懂领域知识,只看代码本身,不可能搞的明白.其次,你得找各种文档:需求文档(要做什么),设计文档(怎么做的),先搞清楚你即将要阅读是 ...

  7. CF360B Levko and Array (二分查找+DP)

    链接:CF360B 题目: B. Levko and Array time limit per test 2 seconds memory limit per test 256 megabytes i ...

  8. 利用ADSL拨号上网方式如何搭建服务器

    序:搭建服务器需要两个条件硬件服务器和固定公网IP,随便一台个人电脑都可以作为硬件服务器,就剩下一个问题,如何获得一个固定公网IP. 第一章 扫盲:ADSL拨号上网方式,本地IP与公网IP的区别 一. ...

  9. PHP数字格式化,每三位逗号分隔数字,可以保留小数

    在报价的时候为了给浏览者更清晰明确的数字,所以需要用到数字格式化,有两种方法,一种自己写函数,另一种当然是系统自带的,其实我更喜欢系统自带的. 先来系统简单的: string number_forma ...

  10. FineUI第二天

    原博文http://www.cnblogs.com/sanshi/archive/2012/02/12/2347789.html 1.首先复制extJS的文件夹到根目录. 2.引用程序集 3.配置配置 ...