EOJ 1082 Easy to AC(枚举+二进制子集法)
来源:互联网 发布:淘宝宝贝囤货怎么设置 编辑:程序博客网 时间:2024/06/08 02:20
题目
题意:判断非负整数 n (n<=1 000 000)能否表示为各不相同的非负数字的阶乘之和,比如9 = 1!+2!+3!
解题思路
由于这些非负数字可以不是相邻的,所以要枚举所有的组合,那么就可以用二进制取子集的方法。
利用二进制的“开关”特性枚举;
具体为:假设给定集合A大小为n,则想象A = {a[0], a[1], …, a[n-1]}的每个元素对应一个开关位(0或1),0表示不出现,1表示出现;当每个元素的开关位的值确定时,就得到一个子集,因此共有2^n-1种情况(全0为空集);
我们利用区间[1, 2^n-1]上的每个整数来对应每个子集,对应方法是:遍历该整数二进制表示的每一位,若该位为1则相应子集中存在对应元素,否则不存在。
在本题中,由于
遍历
需要注意的是:
- 提前打表可以节约后续的计算时间,即将所有满足题意的数先标记出来,判断时直接查询即可。
- 子集法中的0(空集)在本题属于特殊情况,因为0不能由其它数阶乘得到,但在枚举时中会被标记。
AC代码
#include <iostream>using namespace std;const int maxn = 1e7 << 1;bool judge[maxn]; //打表判断i是否为阶乘之和int fac[15]; //存放阶乘void init(){ //计算阶乘 fac[0] = 1; for (int i = 1; i <= 10; ++i) fac[i] = fac[i-1] * i; //打表 fill(judge, judge+maxn, false); int sum = 0; for (int i = 0; i < (1<<10); ++i) //二进制子集法,遍历2^10-1个子集 { sum = 0; for (int j = 0; j < 10; ++j) //移位检测1出现的位置 if (i & (1<<j)) sum += fac[j]; judge[sum] = true; } judge[0] = false; //特殊:0不是阶乘之和!}int main(){ int n, m; init(); while (cin >> n && n >= 0) { if (judge[n]) cout << "YES" << endl; else cout << "NO" << endl; } return 0;}
阅读全文
0 0
- EOJ 1082 Easy to AC(枚举+二进制子集法)
- 二进制枚举法枚举子集
- 二进制枚举子集
- 二进制枚举集合子集
- 二进制枚举子集
- 二进制枚举子集
- 二进制-枚举子集
- C++二进制枚举子集
- 二进制枚举子集
- 二进制枚举子集
- 使用二进制数枚举子集
- 【UVA】11464-Even Parity(二进制枚举子集)
- HDU 4770 Lights Against Dudely(二进制枚举子集)
- USACO Healthy Holsteins(二进制枚举子集)
- 二进制枚举子集与容斥
- UVA658,隐式图+最短路+二进制子集枚举
- 【UVA】1151 - Buy or Build(二进制枚举子集 + 并查集)
- 习题7-4:切断圆环链(二进制枚举子集+dfs判环)
- XListView 下拉刷新 上拉记载 (此方法只能在Android Studio中使用!)
- C#事件-1
- poj 1328 Radar Installation
- [SDUT](2112 && 1139)数据结构实验之链表七:单链表中重复元素的删除 ---链表操作(线性表)
- 推荐书目1
- EOJ 1082 Easy to AC(枚举+二进制子集法)
- Linux下用Eclipse构建HBase开发环境 (总结13)
- 【004】Java语言(JDK的下载与安装)
- c3p0的简单说明
- Linq基础总结
- 移动端车牌识别SDK之参数要求
- 全面升级Android面试之Service面试题集
- 数据罗盘是个什么玩意儿?
- StateListDrawable简介