SMU Summer 2024 Contest Round 3
2024.7.10 9:00————11:00
过题数4/9
补题数6/9
- A - 寻找素数对
- B - 抱歉
- C - 搬寝室
- D - Nuts
- E - Happy Birthday! 2
- F - Bowls and Dishes
- G - Rush Hour 2
- H - Count Descendants
- I - To 3
A - 寻找素数对
题解:
给出任意偶数m,要求输出俩个最接近的素数对相加为m。
卡了一下的地方是输入任意个整数,注意一下循环条件即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int main() {
bool st[100010];
memset(st,0,sizeof st);
for (int i = 3; i <= 100005; i++) {
for (int j = 2; j*j <= i; j++) {
if (i % j == 0) {
st[i] = true;
}
}
}
int m;
while (cin >> m) {
int l = m/2,r = m/2;
while (st[l] || st[r]) {
l--;
r++;
}
cout << l << ' ' << r << endl;
}
return 0;
}
B - 抱歉
题解:
给定n点m面,求有多少条曲线段。每个点至少有俩条曲线段相连,且曲线段互不相交。
一道数学题,大致枚举一下即可找到规律。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
int m,n;
while (cin >> n, cin >> m) {
if (m == 0 && n == 0) {
break;
}
cout << n+(m-2) << endl;
}
return 0;
}
C - 搬寝室
一道dp题,比赛时看了一眼就知道不会做了,不过是道挺典型的,后来判断条件写了好久,wa了五六发吧。
题解:
在n件物品中挑选2*k件,要求每组俩件,俩件的差平方要求最低。
见注释。
代码:
#include<bits/stdc++.h>
using namespace std;
int a[2005];
int dp[2005][2005];
//代表从i件物品中,左手拿j件时的最小疲劳度。
int main() {
int n,k;
while(cin >> n >> k){
//不知道有多少组数据
for (int i = 1; i <= n; i++) {
cin >> a[i];
}sort(a+1,a+n+1);
//可以直接计算差平方,不需要再比较前后俩者。
for (int i = 1; i <= n; i++) {
for (int j = 1; j*2 <= i; j++) {
dp[i][j] = dp[i-2][j-1] + (a[i]-a[i-1]) * (a[i]-a[i-1]);
//状态方程,取这俩件的疲劳度
if(i > 2 * j) {
dp[i][j] = min(dp[i][j],dp[i-1][j]);
//如果存在,再比较一下能不能不管这个
}
}
}
cout << dp[n][k] << endl;
}
return 0;
}
D - Nuts
题解:
n棵树,每棵树上a【i】个🌰,大于10的就拿走。
代码:
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int a[n];
long long sum = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (a[i] > 10)sum+=(a[i]-10);
}
cout << sum << endl;
return 0;
}
F - Bowls and Dishes
英文题面真是看的我俩眼一抓瞎,本来以为是线性规划的,硬着头皮写了一个小时,后来下来发现是爆搜,一整个无语住了。
题解:
给出n个盘子,m种状况,k个人手里拿着球,可以放在c盘或d盘上,求最多可以满足多少种状况。
k最大到16,且只有取与不取俩种情况,直接dfs爆搜即可。具体见注释。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<pair<int,int>>ap;
vector<pair<int,int>>ac;
int k;
int js[105];
int st[105];
int yjs[105];
int c,d;
int res = 0;
void dfs(int p) {
if(p == k) {
int ls = 0;
// for (int i = 1; i < 5; i++) {
// cout << st[i] << ' ';
// }
for (int i = 0; i < m; i++) {
if (st[ap[i].first] && st[ap[i].second]) {
ls++;
// cout << ap[i].first << ' ' << ap[i].second;
}
}
if (ls > res) {
res = ls;
}
return ;
}
st[ac[p].first]++;
dfs(p+1);
st[ac[p].first]--;
st[ac[p].second]++;
dfs(p+1);
st[ac[p].second]--;
//这一块注意一下,太久没写dfs了,一开始直接用的bool数组,但是是不可行的,可能前面已经truel,返回的时候又遇到却把它变成false。
}
int main() {
cin >> n >> m;
memset(js,0,sizeof js);
memset(yjs,0,sizeof yjs);
memset(st,0,sizeof st);
for (int i = 0; i < m; i++) {
int a,b;
cin >> a >> b;
ap.push_back({a,b});
js[a]++;
js[b]++;
}
cin >> k;
for (int i = 0; i < k; i++) {
cin >> c >> d;
ac.push_back({c,d});
}//一个挺常规的输入方式,可算给我记住了。
dfs(0);
//从最底层开始
cout << res << endl;
return 0;
}
I - To 3
其实当时ac了,但我的方法应该问题挺大,太暴力了,就看一下标准方法吧。就十六位数的话,好像也可以爆搜一下?
题解:
给出一个最长可达十八位数的数字n,去掉任意个数字后连接其它数字,组成的数字是三的倍数的话,输出最少需要删去的数字个数。若是不可以实现,输出-1。
利用三的倍数的数字的各个位数相加也是三的倍数。数据较小可以用二进制枚举。
代码:
以下是比赛代码:
#include<bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
long long n[20];
n[0] = 0;
n[1] = 0;
n[2] = 0;
long long res = 0;
for (int i = 0; i < s.length(); i++) {
res += (s[i]-'0');
n[(s[i] - '0')%3]++;
}
if (res % 3 == 0) {
cout << 0 << endl;
}
else {
if (n[1] + 2*n[2] < 3) {
if (n[0] != 0) {
cout << s.length() - n[0];
}
else cout << -1 << endl;
}
else {
long long ls = (n[1] + 2*n[2])% 3;
if (ls == 1) {
if (n[1] == 0) {
if (n[0] != 0) {
cout << s.length() - n[0];
}
else cout << -1 << endl;
}
else cout << 1 << endl;
}
else {
if (n[2] != 0) cout << 1 << endl;
else {
if (n[1] >= 2) cout << 2 << endl;
else {
if (n[0] != 0) {
cout << s.length() - n[0];
}
else cout << -1 << endl;
}
}
}
}
}
return 0;
}
以下是补题代码:
#include<bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
int k = s.size();
int res = 30;
for (int i = 0; i < (1ll << k); i++) {
string q;
for (int j = 0; j < k; j++) {
if (i & (1 << j)) {
q += s[j];
}
}
if (q.empty()) continue;
int m = q.size();
//全部都不选的情况
if(stoll(q) % 3 == 0) {
res = min(res,k - m);
}
}
if(res == 30)res = -1;
//无法实现的情况
cout << res << endl;
return 0;
}