第三届里奇杯编程大赛(初赛)题解
A.签到
签到题,直接输出即可。
#include <bits/stdc++.h>
using namespace std;
int main()
{
cout << "Hello Liqi contest";
return 0;
}
B.挂科
读取到每个人的成绩后,判断符合挂科条件(分数$ < p$ )就 \(res\) 增加一位同学 。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n, p, a[N], res;
int main() {
scanf("%d%d", &n, &p);
for(int i=1; i<=n; i++) {
scanf("%d", &a[i]);
if(a[i] < p) res++;
}
printf("%d\n", res);
return 0;
}
C.送外卖
经过论证,可以发现,沿着坐标轴,从左到右一口气送完外卖是最佳方案。
故将求出 \(a\) 的最大值与最小值后直接相减即可。
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <cstring>
#include <cmath>
#define fi first
#define se second
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const double eps = 1e-4;
const int N = 110;
int n;
void solve() {
scanf("%d", &n);
int minv = 1e9, maxv = 0;
for(int i=1; i<=n; i++) {
int x; scanf("%d", &x);
minv = min(minv, x);
maxv = max(maxv, x);
}
printf("%d\n", maxv-minv);
}
int main() {
// multiple case
// int t; scanf("%d", &t);
// while(t--) {
// solve();
// }
// single case
solve();
return 0;
}
D.分弹珠
每个弹珠都一模一样,故弹珠分配方案的不同只有每个人分的的弹珠多少。
每个人能分得的弹珠数量区间是 \([1, n-1]\) ,故方案数为 \(n-1\) 。这里直接把弹珠数量为 \(1\) 的情况(没有合理的分配方案)也涵盖了。
#include <bits/stdc++.h>
using namespace std;
int n;
int main()
{
cin >> n;
cout << n - 1;
return 0;
}
E.加倍整数
比起判断某个数是否为加倍整数,不如直接构造加倍整数出来,判断他与 \(n\) 的关系。
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <cstring>
#include <cmath>
#define fi first
#define se second
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const double eps = 1e-4;
const int N = 1e6+10;
ll n;
// 将x变为xx的加倍整数
inline ll bianshen(ll x) {
string s = to_string(x);
s = s + s;
return stoll(s);
}
void solve() {
cin >> n;
ll res = 0;
for(ll i = 1; i < N; i++) {
ll x = bianshen(i);
if(x <= n) res++;
}
cout << res << endl;
}
int main() {
// multiple case
// int t; scanf("%d", &t);
// while(t--) {
// solve();
// }
// single case
solve();
return 0;
}
F.大学生特种兵
假如有一段路程为 \(1->2->4->5->3\),则他旅行的起点可以为其中的任意一个,终点为起点后的任意一个。故我们可以枚举起点,然后搜索他能够去到哪些终点。
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int N = 2010;
int n, m, st[N];
vector<int> e[N];
// 任何dfs的u都可能为终点
void dfs(int u, int &sum) {
st[u] = true;
sum++;
for(auto ne:e[u]) {
if(st[ne]) continue;
dfs(ne, sum);
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i=1; i<=m; i++) {
int a, b;
scanf("%d%d", &a, &b);
e[a].push_back(b);
}
int res = 0;
for(int i=1; i<=n; i++) {
memset(st, 0, sizeof(st));
// 这里的表示起点为i
dfs(i, res);
}
printf("%d\n", res);
return 0;
}
G(Ex).不许6
\(a = [1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, ...]\)。从这里可以发现这个数字世界就是一个使用数字 \(0, 1, 2, 3, 4, 5, 7, 8, 9\) 的九进制。故我们将获取到的数字从十进制转换为九进制即可,注意把转换后的 \([6, 8]\) 变为 \([7,9]\)。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
using ll = long long;
void solve() {
ll k; scanf("%lld", &k);
vector<ll> res;
while(k) {
res.push_back(k%9);
k /= 9;
}
reverse(res.begin(), res.end());
for(auto &x:res) {
if(x >= 6) x++;
printf("%lld", x);
}
puts("");
}
int main() {
int t; scanf("%d", &t);
while(t--) {
solve();
}
return 0;
}
不忘初心方得始终