选择题
编程题
第一题
使用桶去统计每个字母个数
#include<iostream>
using namespace std;
// 素数判断
bool is_prime(int n){
if(n <= 1) return false; // 0和1都不是素数
for(int i = 2; i <= n / i; i ++ ){
if(n % i == 0) return false;
}
return true;
}
int main(){
char c[200];
cin >> c;
// 统计字母个数, 0下标记录'a'的个数, 1下标记录'b'的个数,..., 25下标记录'z'的个数
int bucket[30] = {};
for(int i = 0; c[i]; i ++ ){
bucket[c[i] - 97] ++ ;
}
// 查找最大值和最小值, 最小值查找时要注意跳过0
int Max = 0, Min = 200;
for(int i = 0; i < 26; i ++ ){
if(bucket[i] == 0) continue;
Max = max(Max, bucket[i]);
Min = min(Min, bucket[i]);
}
if(is_prime(Max - Min)) cout << "Yes";
else cout << "No";
return 0;
}
第二题
高精度加法模板题
#include<bits/stdc++.h>
using namespace std;
// 高精度加法
vector<int > add(vector<int > &a, vector<int > &b){
vector<int > c;
int t = 0; // 记录是否有进位
for( int i = 0; i < a.size() || i < b.size() ; i ++ ){
if( i < a.size() ) t += a[i];
if( i < b.size() ) t += b[i];
c.push_back(t % 10); // 当前个位存进数组中
t /= 10;
}
if(t) c.push_back(t); // 判断最高位是否有进位
return c;
}
int main(){
// 高精度输入
string A,B,C;
cin >> A >> B >> C;
// 数组逆序存储输入数字
vector<int > a, b, c;
for( int i = A.size() - 1; i >= 0; i -- ) a.push_back(A[i] - '0');
for( int i = B.size() - 1; i >= 0; i -- ) b.push_back(B[i] - '0');
for( int i = C.size() - 1; i >= 0; i -- ) c.push_back(C[i] - '0');
auto ans = add(a,b); // ans = a + b;
ans = add(ans, c); // ans = ans + c;
for( int i = ans.size() - 1; i >= 0; i --) printf("%d",ans[i]);
return 0;
}
第三题
贪心+覆盖问题
贪心点:从半径大的从大到小进行选取
本题保证
2
<
R
i
<
15
2 < R_i < 15
2<Ri<15,故对于宽度的覆盖不用进行考虑,只需要对该喷水装置放进去后长度的覆盖进行考虑即可。
第
i
i
i 个喷水装置能够覆盖的长度为:
l
i
=
(
R
i
2
−
2
2
)
l_i = \sqrt{(R_i^2 - 2^2)}
li=(Ri2−22)
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
double l[700];
bool cmp(double a, double b){
return a > b;
}
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i ++ ){
double r;
cin >> r;
l[i] = sqrt(r * r - 2 * 2); // 计算覆盖的长度
}
sort(l + 1, l + n + 1, cmp); // 从大到小排序
double s = 0; // 计算覆盖总长度
bool flag = false; // 假设不能完全覆盖
for(int i = 1; i <= n; i ++ ){
s += 2 * l[i]; // 左右长度
if(s >= 40){
cout << i << endl; // 输出需要喷水装置个数
flag = true; // 能够完全覆盖
break;
}
}
if(!flag) cout << "NULL" <<endl;
return 0;
}
第四题
全排列+完全错排+乘法原理
每行数字不同:完全错排
每列数字不同:全排列
#include<iostream>
using namespace std;
// 用 ll 代替 long long
typedef long long ll;
// 全排列
ll arrange(int n){
ll s = 1;
for(int i = 1; i <= n; i ++ ){
s *= i;
}
return s;
}
// 完全错排
ll literal(int n){
ll f[20];
f[1] = 0, f[2] = 1;
for(int i = 3; i <= n; i ++ ){
f[i] = (i - 1) * f[i - 2] + (i - 1) * f[i - 1];
}
return f[n];
}
int main(){
int n;
cin >> n;
cout << arrange(n) * literal(n);
return 0;
}
第五题
该问题为01背包问题,但实际问题数据量较小,物品数量最多30,所以可以使用递归。
#include<iostream>
using namespace std;
int weight[40];
int v, n;
int ans; // 记录答案
// 函数定义为前dep-1个物品, 能凑出的体积为total
void dfs(int dep, int total){
ans = min(ans, v - total); // 每次有新的体积产生时, 更新答案
if(dep > n) return; // 物品已经取完
if(total + weight[dep] <= v) dfs(dep + 1, total + weight[dep]); // 取第dep个物品, 保证不超过箱子容量
dfs(dep + 1, total); // 不取第dep个物品
return;
}
int main(){
cin >> v >> n;
ans = v;
for(int i = 1; i <= n; i ++ ){
cin >> weight[i];
}
dfs(1, 0);
cout << ans << endl;
return 0;
}