# [NOIP2002 普及组] 选数
## 题目描述
已知 n 个整数 x1,x2,……,xn,以及 1 个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
## 输入格式
第一行两个空格隔开的整数 n,k(1 < n <= 20,k<n)。
第二行 n 个整数,分别为 x1,x2,……,xn(1 <= xi <= 5* 10^6)。
## 输出格式
输出一个整数,表示种类数。
## 样例 #1
### 样例输入 #1
```
4 3
3 7 12 19
```
### 样例输出 #1
```
1
```
代码
#include <bits/stdc++.h>
using namespace std;
long long g[50];
long long j[50];
long long sum,n,k;
long long ss(long long x)
{long long y;for(y=2;y<x;y++){if(x%y==0)return 0;}return 1;
}
long long dfs(long long h,long long k1,long long s)
{if(k1==k){if(ss(s))sum++;return 0;}else{if(h<=n){dfs(h+1,k1+1,s+g[h]);dfs(h+1,k1,s);}return 0;}
}
int main()
{long long x,y,z;scanf("%lld%lld",&n,&k);for(x=1;x<=n;x++)scanf("%lld",&g[x]);dfs(1,0,0);printf("%lld",sum);return 0;
}
# 奇怪的电梯
## 题目描述
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第 i 层楼(1 <= i <= N)上有一个数字 Ki(0 <= Ki <= N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如: 3, 3, 1, 2, 5 代表了 Ki(K1=3,K2=3,……),从 1 楼开始。在 1 楼,按“上”可以到 4 楼,按“下”是不起作用的,因为没有 -2 楼。那么,从 A 楼到 B 楼至少要按几次按钮呢?
## 输入格式
共二行。
第一行为三个用空格隔开的正整数,表示 N, A, B(1 <= N <= 200,1 <= A, B <= N)。
第二行为 N 个用空格隔开的非负整数,表示 Ki。
## 输出格式
一行,即最少按键次数,若无法到达,则输出 `-1`。
## 样例 #1
### 样例输入 #1
```
5 1 5
3 3 1 2 5
```
### 样例输出 #1
```
3
```
## 提示
对于 100 % 的数据,1 <= N <= 200,1 <= A, B <= N,0 <= Ki <= N。
本题共 16 个测试点,前 15 个每个测试点 6 分,最后一个测试点 10 分。
代码
#include <bits/stdc++.h>
using namespace std;
int g[210];
int j[210][2];
int j2[210];
int l=1,r=0,a,b,n;
int bfs()
{while(l<=r){int x=j[l][0];if(x==b)return j[l][1];if(g[x]==0){l++;continue;}if(x+g[x]<=n&&j2[x+g[x]]!=1){j[++r][0]=x+g[x];j[r][1]=j[l][1]+1;j2[x+g[x]]=1;}if(x-g[x]>=1&&j2[x-g[x]]!=1){j[++r][0]=x-g[x];j[r][1]=j[l][1]+1;j2[x-g[x]]=1;}l++;}return -1;
}
int main()
{int x,y;scanf("%d%d%d",&n,&a,&b);for(x=1;x<=n;x++)scanf("%d",&g[x]);j[++r][0]=a;j[r][1]=0;j2[a]=1;printf("%d",bfs());return 0;
}
# 学生分组
## 题目描述
有 n 组学生,给出初始时每组中的学生个数,再给出每组学生人数的上界 R 和下界 L\(L <= R),每次你可以在某组中选出一个学生把他安排到另外一组中,问最少要多少次才可以使 N 组学生的人数都在 [L,R] 中。
## 输入格式
第一行一个整数 n,表示学生组数;
第二行 n 个整数,表示每组的学生个数;
第三行两个整数 L,R,表示下界和上界。
## 输出格式
一个数,表示最少的交换次数,如果不能满足题目条件输出 -1。
## 样例 #1
### 样例输入 #1
```
2
10 20
10 15
```
### 样例输出 #1
```
5
```
## 提示
### 数据范围及约定
对于全部数据,保证 1<= n <= 50。
代码
#include <bits/stdc++.h>
using namespace std;
long long g[55];
int main()
{long long x,y=0,z=0,n,l,r,sum=0;scanf("%lld",&n);for(x=1;x<=n;x++){scanf("%lld",&g[x]);sum+=g[x];}scanf("%lld%lld",&l,&r);if(sum>r*n||sum<l*n){printf("-1");return 0;}else{for(x=1;x<=n;x++){if(g[x]>r){y=y+g[x]-r;}if(g[x]<l){z=z+l-g[x];}}}printf("%lld",max(y,z));return 0;
}