SMU Winter 2023 Round #5 (Div.2)

A题 Lucky?

题意:给一个六位数,如果前三位和后三位上的数字之和相等就输出yes否则输出no。

思路:将六位数转化成字符串,然后求前三个字符和后三个字符所对应的数字之和。

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
const int N=110;
int main() {
    IOS;
    int t;
    cin>>t;
    while(t--) {
        string s;
        cin >> s;
        int a, b;
        a = (s[0] - '0') + (s[1] - '0') + (s[2] - '0');
        b = (s[s.size() - 1] - '0') + (s[s.size() - 2] - '0') + (s[s.size() - 3] - '0');
        if (a == b)cout << "Yes" << '\n';
        else cout << "NO" << '\n';
    }
    return 0;
}

B题 EqualCandies

题意:给你n】个盒子,有a[i]个糖果,问最少拿多少块糖使盒子内的糖果相等。

思路:直接贪心,肯定要以最少的那个盒子为标准,因为不能添加,排序后一个一个减求和即可。

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
const int N=110;
int a[N];
int main() {
    IOS;
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int ans=0;
        for(int i=0;i<n;i++)cin>>a[i];
        sort(a,a+n);
        for(int i=1;i<n;i++){
            ans+=a[i]-a[0];
        }
        cout<<ans<<'\n';
    }
    return 0;
}

c题 Most Similar Words

题意:对于每个测试用例,给你 n 个等长 m 的单词,单词的字母都由小写拉丁字母组成,你可以按字母顺序更改字母(比如 e 可以改为 d 或 f ),但 a 与 z 不能互改。问你哪一对单词,使它们单词相同所需改的次数最少,输出最少的次数

思路:直接枚举每个字符串的所有情况求最小即可。

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
const int N=110;
int a[N];
int main() {
    IOS;
    int t;
    cin>>t;
    while(t--){
        int n,m;
        int mn=INT_MAX;
        cin>>n>>m;
        string s[n+10];
        for(int i=0;i<n;i++)cin>>s[i];
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                int ans=0;
                for(int k=0;k<s[i].size();k++){
                    if(s[i][k]<=s[j][k])ans+=(s[j][k]-s[i][k]);
                    else ans+=(s[i][k]-s[j][k]);
                }
                mn=min(mn,ans);
            }
        }
        cout<<mn<<'\n';
    }
    return 0;
}

D题 X—Sum

题意:对于每个测试用例,给你 1 个 n 行 m 列的棋盘,棋盘的每个格子上都有一个值,给你一个棋子,棋子可以斜向四面八方攻击,问你怎么摆放棋子可以获得最大的值,输出最大值。

思路:也是暴力求解,每个格子就求一下对角线的格子以及自己个内的数字之和,求对角线就是从1开始枚举到n和m的对大致,加个判断条件只有在边界内才加上,最后再求最大值,也事先可以先求每一条对角线的值,到哪一个再加,复杂度会降低。


#include<bits/stdc++.h>
using namespace std;
const int N=210;
int f[N];
int g[N][N];
int dx[]={-1,-1,1,1};
int dy[]={-1,1,-1,1};
int main()
{
    int t ;
    cin>>t;
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>g[i][j];
            }
        int sum=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int ans=0;
                ans+=g[i][j];
                for(int l=1;l<=max(n,m);l++)
                {
                    for(int k=0;k<4;k++)
                    {
                        int a=l*dx[k]+i;
                        int b=l*dy[k]+j;
                        if(a>0&&a<=n&&b>0&&b<=m)
                            ans+=g[a][b];
                    }
                }
                sum=max(sum,ans);
            }
        cout<<sum<<endl;
    }
    return 0;
}

E题 Eating Queries

题意:给你 n 颗糖,每个糖果都有糖量,有 q 个查询,问你最少吃多少颗糖,才能使总糖量大于查询值,输出最小糖数,如果达不到查询值,输出 -1 。

思路:看到总量,可以想到前缀和,大于查询值,就是找值,可以用二分,所以这题就是前缀和+二分就可以过了。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int x, y;
int a[N];
int b[N];
int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> x >> y;
        for (int j = 0; j < x; j++) {
            cin >> a[j];
        }
        sort(a, a + x,greater<int>());
        for (int j = 0; j <x ; j++) {
            if (j == 0) {
                b[j] = a[j];
            }
            else {
                b[j] = b[j - 1] + a[j];
            }
        }
        for (int j = 0; j < y; j++) {
            int k;
            cin >> k;
            if (k > b[x-1]) {
                cout << -1 << endl;
                continue;
            }
            int l=0, r=x-1;
            while (l < r)
            {
                int mid = l + r >> 1;
                if (b[mid] >= k) r = mid;
                else l = mid + 1;
            }
            if (k <= b[l]) cout << l+1 << "\n";
            else cout << "-1\n";
        }
    }
}

F题 Longest Strike

题意:给你一组序列,让你找出一组l,r要求所有在lr之间的数的数量大于k

思路:看数据范围,序列的数据范围不高,但是所给数的范围较大,所以可以采用离散化,可以手写一个离散化然后再双指针算出最大的区间,先排序,然后再记忆所有不同的数,和记录数量,最后再双指针遍历即可

#include<bits/stdc++.h>

using namespace std;
const int N = 3 * 1e5 + 100;
int T;
int n, m;
int a[N], s[N], num[N];

bool cmp(long long aa, long long b) {
    return aa > b;
}

int main() {
    cin >> T;
    while (T--) {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        sort(a + 1, a + 1 + n);
        int idx = 0;
        for (int i = 1; i <= n; i++) {
            int j = i;
            while (a[j] == a[j + 1] && (j + 1 <= n))j++;
            s[++idx] = j - i + 1;
            num[idx] = a[i];
            i = j;
        }
        int l = -1, r = -1, len = -1;
        for (int i = 1; i <= idx; i++) {
            int j = i;
            while ((j + 1 <= idx) && s[j] >= m && s[j + 1] >= m && (num[j + 1] == num[j] + 1))j++;
            if ((l == -1 || num[j] - num[i] > len) && s[j] >= m) {
                l = i, r = j;
                len = num[j] - num[i];
            }
            i = j;
        }
        if (l != -1) {
            printf("%d %d\n", num[l], num[r]);
            // cout << num[l] << num[r] << endl;
        } else printf("-1\n");
    }
    return 0;
}

H题 Maximum Crossings (Easy Version)

题意:就是求逆序对

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
int a[N], n;

signed main()
{
    int t; cin>>t;

    while(t--)
    {
        cin>>n;
        for(int i=1; i<=n; ++i) cin>>a[i];
        int res = 0;
        for(int i=1; i<n; ++i)
        {
            for(int j=i+1; j<=n; ++j)
            {
                if(a[i] >= a[j]) ++res;
            }
        }
        cout<<res<<'\n';
    }

    return 0;
}

SMU Winter 2023 Round #7 (Div.2)

A题 解开束缚缠丝Ⅱ

题意:求给出的n个字符最长可以组成多长的回文串。

思路:就是统计字符出现的次数,要么全部是偶数全部可以构成回文串,如果有奇数,那么只有其中一个奇数的字符串可以放入回文串中,用map来做就可以了。

#include<bits/stdc++.h>
 using namespace std;
 int main() {
     int t;
     cin>>t;
     while(t--){
         int n;
         cin>>n;
         map <char,int> mp;
         int ans=0;
         for(int i=0;i<n;i++){
             char ch;
             cin>>ch;
             mp[ch]++;
         }
         for(auto i:mp){
             if(i.second%2!=0)ans++;
         }
         //cout<<ans<<' ';
         cout<<n-ans+1<<endl;
     }
     return 0;
 }

B题 7 的意志

题意:求有最多几个区间的和为7777

思路:先进行前缀和预处理,然后枚举每一个可能的区间和的左端点,寻找可行的右端点。一个左端点最多只有一个可行的右端点进行匹配

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, ans;
int a[100005], s[100005];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    ll t;
    cin>>t;
    while (t--) {
        cin >> n;
        s[0] = ans = 0;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i];
            s[i] = s[i - 1] + a[i];
        }
        for (int i = 1; i <= n; ++i) {
            ll tar = s[i - 1] + 7777;
            ll x = lower_bound(s + 1, s + n + 1, tar) - s;
            if (s[x] == tar) ans++;
        }
        cout << ans << '\n';
    }
    return 0;
}

F题 月光奏鸣曲

题意:给你两个正方形的数字矩阵,可以逆时针和顺时针转动,问最少转几次让两个矩阵相等。

思路:肯定只能往一个方向转,不然只要有一个向另外一个方向转了,就会抵消本方向的一次,相当于没有转,但是操作次数却多了两次,题目求最少,并且做多只有可能转三次,第四次就回原位置了,写四个转零次,一次,两次,三次的函数判断一下即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

int n;
int a[25][25], b[25][25];

bool check0() {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (b[i][j] != a[i][j]) return false;
        }
    }
    return true;
}

bool check1() {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (b[i][j] != a[n - j + 1][i]) return false;
        }
    }
    return true;
}

bool check2() {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (b[i][j] != a[j][n - i + 1]) return false;
        }
    }
    return true;
}

bool check3() {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (b[i][j] != a[n - i + 1][n - j + 1]) return false;
        }
    }
    return true;
}

void main2() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin >> a[i][j];
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin >> b[i][j];
        }
    }
    if (check0()) cout << 0 << '\n';
    else if (check1()) cout << 1 << '\n';
    else if (check2()) cout << 1 << '\n';
    else if (check3()) cout << 2 << '\n';
    else cout << -1 << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    LL _;
    cin >> _;
//	_ = 1;
    while (_--) main2();
    return 0;
}


H题 简单的 LRU 问题

就是根据题目所说模拟一下就可以了,但是有点复杂,要耐得住性子

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

int n, m, mx;
int a[105][10];
string hx = "0123456789abcdef";


int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> m;
    mx = 0;
    cout << "+------+";
    for (int i = 0; i < n; ++i) {
        cout << "--------+";
    }
    cout << '\n';
    cout << "|      |";
    for (int i = 0; i < n; ++i) {
        cout << "  0x";
        int a = i / 16, b = i % 16;
        cout << hx.substr(a, 1) << hx.substr(b, 1) << "  |";
    }
    cout << '\n';
    cout << "+------+";
    for (int i = 0; i < n; ++i) {
        cout << "--------+";
    }
    cout << '\n';
    for (int i = 0; i < m; ++i) {
        int x; cin >> x;
        if (i == 0) a[0][0] = x;
        else {
            int have = 0;
            for (int j = 0; j <= mx; ++j) {
                if (a[i - 1][j] == x) {
                    have = 1; break;
                }
            }
            if (have) {
                int k = 0;
                for (int j = 0; j <= mx; ++j) {
                    if (a[i - 1][j] == x) continue;
                    a[i][k++] = a[i - 1][j];
                }
                a[i][mx] = x;
            }
            else {
                if (mx < n - 1) {
                    for (int j = 0; j <= mx; ++j) {
                        a[i][j] = a[i - 1][j];
                    }
                    a[i][++mx] = x;
                }
                else {
                    int k = 0;
                    for (int j = 1; j <= mx; ++j) {
                        a[i][k++] = a[i - 1][j];
                    }
                    a[i][mx] = x;
                }
            }
        }
        cout << "| 0x";
        int A, B, C, D; A = i / 16; B = i % 16;
        cout << hx.substr(A, 1) << hx.substr(B, 1) << " |";
        for (int j = 0; j <= mx; ++j) {
            cout << " 0x";
            int tmp = a[i][j];
            A = tmp / 4096; tmp -= A * 4096;
            B = tmp / 256; tmp -= B * 256;
            C = tmp / 16; tmp -= C * 16;
            D = tmp;
            cout << hx.substr(A, 1) << hx.substr(B, 1);
            cout << hx.substr(C, 1) << hx.substr(D, 1) << " |";
        }
        for (int j = mx + 1; j < n; ++j) {
            cout << "        |";
        }
        cout << '\n';
        cout << "+------+";
        for (int i = 0; i < n; ++i) {
            cout << "--------+";
        }
        cout << '\n';
    }
    return 0;
}

I题 好想听肆宝唱歌啊

题意:给你几首个的名字以及喜爱它的程度,数字越大喜爱程度越高,再给你个数字k,就是最爱的前k首歌曲已经点了,现在要点目前情况下最喜爱的歌曲,输出该歌曲的名字。

思路:使用一个结构体进行排序,如果输出k+1首歌曲的名字就可以了。

#include<bits/stdc++.
using namespace std;
typedef long long LL;
const int N=100010;
int n;

struct S {
    int w;
    string x;
}s[N];


bool cmp(S a,S b){
    return a.w>b.w;
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> s[i].w >> s[i].x;
    sort(s + 1, s + n + 1, cmp);
    int k;
    cin >> k;
    cout << s[k + 1].x;
    return 0;
}



J 题 毁灭凤凰人

#include<bits/stdc++.h>
using namespace std;
int n, m;
int mxa = 0, a = 0, b = 0;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        int res, x;
        cin >> res;
        if (res == 0) {
            cin >> x;
            mxa = max(mxa, x);
        } else if (res == 1) a = 1;
        else b = 1;
    }
    if (m == 0 && mxa >= 2500 && a) {
        cout << "haoye\n";
        return 0;
    } else if (m == 1 && mxa > 2100 && a) {
        cout << "haoye\n";
        return 0;
    } else if (b && n > 1) {
        cout << "haoye\n";
        return 0;
    } else cout << "QAQ\n";
    return 0;
}


### K题 欢迎来到杭师大

题意:给你一个n,输出n个Welcome to HZNU,每个要换行

思路:先定义一个字符串,用个循环输出即可。

#include<bits/stdc++.h> #define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr) using namespace std; int main() { IOS; int n; cin>>n; string s="Welcome to HZNU"; while(n--){ cout<<s<<'\n'; } return 0; }


### L题 Ayanoto 变形记
题意:给n个点,每次条x步,问再其中一个位置,能不能跳回原来的位置

思路:我们可以知道,总共跳的步数就是两个数的最小公倍数,但两个不为零的数肯定有最小公倍数,所以只要跳的x不为零,都可以,为零就不行。

#include<bits/stdc++.h> #define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr) #define ll long long using namespace std; int main() { IOS; ll t; cin>>t; while(t--) { ll a, b; cin >> a >> b; if (b == 0)cout << "no" << '\n'; else cout << "yes" << '\n'; } return 0; }

### M题 龙学长的教诲
题意:给你一个字符串,他的顺序是1,3,5,6,4,2这样的顺序,但他正确的顺序是1,2,3,4,5,6,将正确的输出出来,标点符号在最后

思路:再读入的时候,当这个字符串的结尾有标点符号时就结束读入,将标点符号记下来,按顺序输出就可以了,记得最后加标点符号,再注意一下具体的格式。

#include<bits/stdc++.h> using namespace std; typedef long long LL;

int n; string x[1005]; char op;

void print(int id) { if (id != n) cout << x[id]; else { int len = x[id].length(); for (int i = 0; i < len - 1; ++i) { cout << x[id][i]; } } }

int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while (t--){ n=0; while (cin >> x[++n]) { int len = x[n].length(); if (x[n][len - 1] == '.' || x[n][len - 1] == '!' || x[n][len - 1] == '?') { op = x[n][len - 1]; break; } } for (int i = 1; i <= n / 2; ++i) { print(i); cout << ' '; print(n - i + 1); if (i < n / 2 or n % 2 == 1)cout << ' '; } if (n % 2 == 1) { print(n / 2 + 1); } cout << op<< '\n'; } return 0; }