SMU Summer 2024 Contest Round 3

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;
}

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值