组合
在n个中随机选m个
模板
//组合(在n个中随机选m个)
#include <bits/stdc++.h>
using namespace std;
int n;
int m;
vector<int>chosen;
void calc(int x) //当前处理到第x个数
{
//如果已经选了m个数 | 剩下的数全部选了也达不到m个
if(chosen.size()>m || chosen.size()+(n-x+1)<m)
return; //剪枝
//全部数字都遍历完了
if(x==n+1)
{
for(int i=0;i<chosen.size();i++)
cout<<chosen[i];
cout<<endl;
return;
}
chosen.push_back(x); //选择当前数
calc(x+1); //处理下一个(递归)
chosen.pop_back(); //不选择当前数
calc(x+1); //递归处理下一个
}
int main()
{
cin>>n>>m;
calc(1);
}
排列
STL库函数:next_permutation()
功能:从当前的排列顺序开始,逐个输出更大的全排列,并把新的排列放在原来的空间里
返回值:是否有下一个排列组合
注意:排列的范围是 [ first , last )
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s="bca";
sort(s.begin(),s.end()); //字符串内部排序,得到最小的全排列
//因为一调用next_permutation()字符串顺序就会变,所以先do一次
do{
cout<<s<<endl;
}while(next_permutation(s.begin(),s.end()));
return 0;
}
模板
#include <bits/stdc++.h>
using namespace std;
int n;
int order[20]; //全排列
bool chosen[20]; //记录当前位置的有没有被选择过
void calc(int k) //第k个位置
{
if(k==n+1)
{
for(int i=1;i<=n;i++)
{
cout<<order[i];
}
cout<<endl;
return;
}
for(int i=1;i<=n;i++)
{
//如果i已经被选择过了,跳过
if(chosen[i])
continue;
//选
chosen[i]=1;
order[k]=i;
calc(k+1);
//不选
chosen[i]=0;
}
}
int main()
{
cin>>n;
calc(1);
}
题
lanqiaoOJ-269
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s,olds;
cin>>s;
olds=s; //记录最初的串
int cnt=0;
sort(s.begin(),s.end());
do{
if(s==olds){
cout<<cnt<<endl;
break;
}
cnt++;
}while(next_permutation(s.begin(),s.end()));
return 0;
}
lanqiaoOJ-572
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
int a[10000]={0};
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<m;i++)
{
next_permutation(a,a+n);
}
int i=0;
for(;i<n-1;i++){
cout<<a[i]<<" ";
}
cout<<a[i];
return 0;
}
子集
用二进制的概念进行对照,子集正好对应了二进制。例如n=3的集合{0,1,2}的子集和二进制数的对应关系是:
子集元素 | 空 | 0 | 1 | 1,0 | 2 | 2,0 | 2,1 | 2,1,0 |
二进制数 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
模板
//输出n个数的所有子集
#include <bits/stdc++.h>
using namespace std;
int a[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
void print_subset(int n)
{
for(int i=0;i<(1<<n);i++)
{
//i:0~2^n,每个i的二进制数对应一个子集
for(int j=0;j<n;j++) //打印i的二进制数中所有的1对应的数
{
if(i&(1<<j)) //从i的最低位开始,检查每一位,如果是1,打印
/*
n=3的情况下
j=0 001
j=1 010
j=2 100
*/
cout<<a[j];
}
cout<<endl;
}
}
int main()
{
int n=3;
print_subset(n);
}
尺取法
同向(快慢指针)
lanqiao美丽的区间
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,s; cin>>n>>s;
int a[100010]={0};
for(int i=0;i<n;i++) cin>>a[i];
int ans=1e8; //存一个很大的数
int sum=0;
//尺取法
/*
i在前,j在后
i一直往前探,直到sum>s
sum>s之后,先记录长度,再移动j,缩短区间长度,直到sum<s
*/
for(int i=0,j=0;i<n;){
if(sum<s){
sum+=a[i];
i++;
}
else{
ans=min(i-j,ans);
sum-=a[j]; //缩短区间长度
j++;
}
}
if(ans==1e8) cout<<0;
else cout<<ans;
return 0;
}
反向
lanqiao回文数判定、找指定和的整数对