[hihocoder1546]集合计数
来源:互联网 发布:网络爬虫的目的和意义 编辑:程序博客网 时间:2024/06/15 13:07
题目描述
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个包含N个整数的集合S={A1, A2, … AN},以及一个给定的整数K,请计算有多少个S的子集满足其中的最大值与最小值的和小于等于K。
例如对于S={4, 2, 5, 8}以及K=7,满足的条件的子集有以下4个:{2}, {2, 4}, {2, 5}, {2, 4, 5}。
输入
第一行包含两个整数N和K。
第二行包含N个整数A1, A2, … AN。
对于30%的数据,1 <= N <= 20
对于70%的数据,1 <= N <= 1000
对于100%的数据,1 <= N <= 100000, 0 <= Ai <= 1000000000, 0 <= K <= 2000000000, A1 ~ AN 两两不同。
输出
输出满足条件的子集数目。由于答案可能非常大,你只需要输出答案除以1000000007的余数。
样例输入
4 7
4 2 5 8
样例输出
4
算法简介
先确认题面,笔者错读了几个地方,导致一直错解:1. 是最大值和最小值的和,这句话本来被笔者理解为了集合的和,修正之后又忘记了是两个的和(对于集合内个数为1的情况,也要加两次) 2. 对于和取模。然后开始解题:
最大值和最小值的和小于某个给定值的子集数目,首先肯定想到要排序。这里笔者直接采用了algorithm里面的sort函数,复杂度应该为
对于排序之后的序列,最简单的方法就是逐一寻找最大值和最小值对,然后求取以两者为最大小值的子集个数:采用第
设排序之后的列表为arr,从小到大排序
1. 若arr[i]+arr[j] <= K,则有arr[i]+arr[k] <= K, for k < j && k >= i
2. 若arr[i]*2 > K,则有arr[i] + arr[j] > K, for any j > i
3. 若arr[i]+arr[j+1] > K,则有arr[i+1]+arr[j+1] > K
利用第一条,对于任意最小值arr[i],只需要找到满足arr[i]+arr[j]<=K中的最大值即可,对于任意k < j && k >= i,arr[k]和arr[i]都可以作为最大小值对。而所有子集的个数为
利用第二条,枚举arr[i]的时候,从小到大,一旦遇到2*arr[i] > K的情况,即可停止枚举。
利用第三条,最小值从小到大的枚举过程中,最大值的枚举也是从大到小,不需要每次都重新搜索arr[j],只需要从arr[i-1]的arr[j]继续向小枚举即可。
利用上诉三条,最终使得复杂度减为
对于
代码
#include <iostream>#include <vector>#include <algorithm>using namespace std;#define MOD 1000000007int N,K;vector<int> arr(100002);int exp_2[100002];int exp2(int i) { if (exp_2[i] == 0) exp_2[i] = (2*exp2(i-1))%MOD; return exp_2[i];}int main(){ exp_2[0] = 1; cin >> N >> K; for (int i = 0;i < N;++i) cin >> arr[i]; sort(arr.begin(),arr.begin()+N);// for (int i = 0;i < N;++i)// cout << arr[i] << ' ';// cout << endl; int rear = N-1; int result = 0; for (int i = 0;i < N && 2 * arr[i] <= K;++i) { result = (result + 1) % MOD; for (;rear >= i && arr[i]+arr[rear] > K;--rear); if (rear >= i) result = (result+exp2(rear-i)-1)%MOD; } cout << result << endl; return 0;}
- [hihocoder1546]集合计数
- HihoCoder1546集合计数
- bzoj2839 集合计数
- [bzoj2839]集合计数
- 集合计数 count
- bzoj 2839 集合计数
- BZOJ 2839 集合计数
- 集合计数 51Nod
- bzoj 2839 集合计数
- 51nod 1352:集合计数
- 51nod 1352 集合计数
- 51Nod 1352 集合计数
- 51 Nod 1352 集合计数
- 容斥原理 集合计数
- jsoi2012省队集训:集合计数
- BZOJ 2839 集合计数 容斥原理
- 51nod 算法马拉松 集合计数
- 51nod 1352 集合计数(扩展欧几里得)
- 线程安全与可重入函数strtok_r()
- 20170810
- 8.11
- Metasploit的Docker安装及其Eternal Blue(永恒之蓝)渗透实现
- tensorflow预训练简单模型及权重文件复用初始化复杂模型
- [hihocoder1546]集合计数
- 2017.8.11
- 2017/8/11
- Action的创建与访问方式
- 919
- 20多条总结学完SymPy库
- Day13
- 拓扑排序 [HNOI2015]菜肴制作
- Maven 项目中pom.xml 文件 Write error