例题(acwing4954. 挑选)
给定一个包含 n个正整数 a1,a2,…,an 的集合。
集合中可能存在数值相同的元素。
请你从集合中挑选一些元素,要求同时满足以下所有条件:
- 被选中元素不少于 2 个。
- 所有被选中元素之和不小于 l 且不大于 r。
- 所有被选中元素之中最大元素与最小元素之差不小于 x。
请问,一共有多少种不同的选法。
注意:
- 不考虑元素顺序{a1,a2} 和 {a2,a1} 应当视为同一种选法。
- 不同元素即使数值相同,也应当视为不同个体,即使 a1=a2,{a1,a3} 和 {a2,a3} 也应当视为不同选法。
输入格式
第一行包含四个整数 n,l,r,x。
第二行包含 n个整数 a1,a2,…,an。
输出格式
一个整数,表示不同选法的数量。
数据范围
前 3个测试点满足 1≤n≤5。
所有测试点满足1≤n≤15,1≤l≤r≤109,1≤x≤106,1≤ai≤106。
输入样例1:
3 5 6 1
1 2 3
输出样例1:
2
输入样例2:
4 40 50 10
10 20 30 25
输出样例2:
2
输入样例3:
5 25 35 10
10 10 20 10 20
输出样例3:
6
算法(二进制枚举)(时间复杂度n*2^n)
代码实现
#include<iostream>
#include<algorithm>
using namespace std;
int a[20];
int main(){
int n,l,r,x;
cin>>n>>l>>r>>x;
for(int i=0;i<n;i++)cin>>a[i];
int ans=0;
for(int i=0;i<1<<n;i++){
int cnt=0,sum=0,minn=1e9,maxx=-1;
for(int j=0;j<n;j++){
if(i >> j & 1){
cnt++;
sum+=a[j];
minn=min(minn,a[j]);
maxx=max(maxx,a[j]);
}
}
if(cnt>=2&&sum>=l&&sum<=r&&maxx-minn>=x)ans++;
}
cout<<ans<<endl;
return 0;
}
核心代码
for(int i=0; i<(1<<n); i++)//二进制枚举//枚举每一个状态
{
for(int j=0; j<n; j++)//枚举该状态下二进制的每一位数值
{
if(i&(1<<j))
}
}