第十二届东南大学短码竞赛 - 决赛题解

dd 2025-03-30 20:26:04 2025-03-30 20:26:38

A. 长码竞赛

不难发现,日期 52020330 中有三个 00,两个 22,两个 33 和一个 55。所以一个一个数字遍历,直到这四种数字数量足够即可。

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

main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        vector<int> cnt(10);
        cnt[0] = 3, cnt[2] = 2, cnt[3] = 2, cnt[5] = 1;
        auto check = [&]() {
            for (auto x : cnt)
                if (x > 0)
                    return false;
            return true;
        };
        int ans = -1;
        for (int i = 1, x; i <= n; i++) {
            cin >> x;
            --cnt[x];
            if (ans == -1 && check())
                ans = i;
        }
        cout << ans << '\n';
    }
}

B. 浮点表示

直接模拟当然是可以的,但其实注意到绝大多数现代处理器使用 IEEE 754 标准定义 double 类型,所以直接将给定的 01 数据存入内存,并让处理器以 double 的形式解析这段内存即可(强制转换为 double 指针,然后解引用)。

#import<bits/stdc++.h>
using namespace std;
main(int t, bitset<64> B) {
    cin >> t;
    while (t--) {
        cin >> B;
        auto x = B.to_ullong();
        printf("%.15e\n", *(double*)&x);
    }
}

直接模拟的代码:

#include <bits/stdc++.h>
using namespace std;
using ld = double;
using ull = unsigned long long;

ull getull(string s) {
    bitset<64> B(s);
    return B.to_ullong();
}

void solve() {
    string s;
    cin >> s;
    string sign = s.substr(0, 1);
    string exponent = s.substr(1, 11);
    string fraction = s.substr(12, 52);
    ull exp = getull(exponent), frc = getull(fraction);
    if (exp == 2047) {
        if (frc == 0)
            cout << (sign == "0" ? "inf" : "-inf") << '\n';
        else
            cout << "nan\n";
    } else if (exp == 0) {
        ld ans = (sign == "0" ? 1 : -1);
        ld mid = ld(frc) / pow(2, 52);
        ans = ans * mid * pow(2, -1022);
        cout << scientific << setprecision(15) << ans << '\n';
    } else {
        ld ans = (sign == "0" ? 1 : -1);
        ld mid = ld(1) + ld(frc) / pow(2, 52);
        ans = ans * mid * pow(2, int(exp) - 1023);
        cout << scientific << setprecision(15) << ans << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}

C. Look and Say

作为一个结果序列,序列长度一定是偶数,并可以分成若干个长度为 2 的子串,每个子串的第一位表示对应字串的第二位数字有多少个。遍历所有的子串,就可以模拟出上一个字串的内容。记录模拟到只剩一个 "1" 时的次数就是答案。

#import<bits/stdc++.h>
using namespace std;
main(int t){
    cin>>t;
    while(t--){
        string s,t;
        int n=1,i,j;
        for(cin>>s;s!="1";++n){
            t="";
            for(i=0;i<s.size();i+=2)
                t+=string(s[i]-'0',s[i+1]);
            s=t;
        }
        cout<<n<<'\n';
    }
}

D. Xor Division

分为两种情况,整个序列异或值为 00 或者整合序列异或值为 x(x>0)x(x>0)

假如整个序列的异或值为 00,那么一定存在一种划分方案将序列分为两段因为 xx=0x\bigoplus x =0,其实随便选择一个位置划分就行。

那么假设整个序列的异或值为 xx,这时候只能把序列分为奇数段(k3)(k\ge 3)且每段异或和为 xx

对于第二种情况,贪心地检查是否存在一个划分的方法即可。

#include <bits/stdc++.h>
using namespace std;
main() {
    int t;
    cin >> t;
    while (t--) {
        int n, s = 0, m;
        cin >> n;
        vector<int> a(n + 1);
        for (int i = 1; i <= n; i++) cin >> a[i], a[i] ^= a[i - 1];
        m = a[n];
        for (int i = 1; i <= n; i++) {
            if (a[i] == m)
                ++s, m ^= a[n];
        }
        cout << (a[n] == 0 || s >= 3 ? "YES\n" : "NO\n");
    }
}

E. 结构体

代码应该写的很清楚了,略,原题见 P9754 CSP-S 2023] 结构体 - 洛谷