2024年第十五屆藍橋杯軟體類國賽 C/C++ B組 個人解法

StelaYuri發表於2024-06-05

暫時不想寫太詳細的題解了,就先只放我的程式碼好了,以後如果想寫了的話再寫寫具體想法吧

今年沒參加正賽,這兩天忽然來了點興趣所以做了做這套題,順便造了些資料放本校OJ上當練習題用

感覺難度和去年比算是持平吧,最難的題比去年要簡單了些的

解法可能不一定是對的,但時間和空間限制我自己都有測試過,問題不大

如有錯誤請指出謝謝~


合法密碼

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

int ans = 0;
string s = "kfdhtshmrw4nxg#f44ehlbn33ccto#mwfn2waebry#3qd1ubwyhcyuavuajb#vyecsycuzsmwp31ipzah#catatja3kaqbcss2th";

bool check(string s)
{
    bool f = false, g = false;
    for(char c : s)
    {
        if(isalpha(c))
            continue;
        if(isdigit(c))
        {
            f = true;
            continue;
        }
        g = true;
    }
    return f && g;
}

int main()
{
    for(int i = 0; i < s.size(); i++)
    {
        for(int j = i + 7; j < s.size() && j - i + 1 <= 16; j++)
        {
            if(check(s.substr(i, j - i + 1)))
                ans++;
        }
    }
    cout << ans;
    
    return 0;
}

選數機率

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

int gcd(int x, int y)
{
    return y == 0 ? x : gcd(y, x % y);
}

bool check(int a, int b, int c)
{
    int c2 = (a + b + c) * (a + b + c - 1) / 2;
    int x, y, z;
    
    x = a * b, y = c2;
    z = gcd(x, y);
    if(x / z != 517 || y / z != 2091)
        return false;
    
    x = b * c, y = c2;
    z = gcd(x, y);
    if(x / z != 2632 || y / z != 10455)
        return false;
    
    x = a * c, y = c2;
    z = gcd(x, y);
    if(x / z != 308 || y / z != 2091)
        return false;
    
    return true;
}

int main()
{
    for(int a = 1; a <= 100; a++)
        for(int b = 1; b <= 100; b++)
            for(int c = 1; c <= 100; c++)
            {
                if(check(a, b, c))
                    cout << a << "," << b << "," << c;
            }
    
    return 0;
}

螞蟻開會

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

int n;
int ux[505], uy[505], vx[505], vy[505];
int ans = 0;
map<int, int> mp;

inline int _hash(int x, int y)
{
    return x * 13331 + y;
}

void add(int x, int y)
{
    if(++mp[_hash(x, y)] == 2)
        ans++;
}

int gcd(int x, int y)
{
    return y == 0 ? x : gcd(y, x % y);
}

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> ux[i] >> uy[i] >> vx[i] >> vy[i];
        if(ux[i] != vx[i])
        {
            if(ux[i] > vx[i])
            {
                swap(ux[i], vx[i]);
                swap(uy[i], vy[i]);
            }
            int dx = vx[i] - ux[i], dy = vy[i] - uy[i];
            int g = abs(gcd(dx, dy));
            dx /= g, dy /= g;
            for(int x = ux[i], y = uy[i]; x <= vx[i]; x += dx, y += dy)
                add(x, y);
        }
        else
        {
            if(uy[i] > vy[i])
                swap(uy[i], vy[i]);
            for(int x = ux[i], y = uy[i]; y <= vy[i]; y++)
                add(x, y);
        }
    }
    cout << ans << "\n";
    
    return 0;
}

立定跳遠

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

int n, m;
int a[100005], b[100005];

bool check(int d)
{
    int t = m + 1; // 把2L看作多一個跳板
    for(int i = 1; i <= n; i++)
    {
        t -= (b[i] - 1) / d;
        if(t < 0)
            return false;
    }
    return true;
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        b[i] = a[i] - a[i - 1];
    }
    sort(b + 1, b + n + 1);
    int l = 1, r = 1e8;
    while(l <= r)
    {
        int mid = l + r >> 1;
        if(check(mid))
            r = mid - 1;
        else
            l = mid + 1;
    }
    cout << l;
    
    return 0;
}

最小字串

#include<bits/stdc++.h>
using namespace std;
char s[100005], t[100005];
int main()
{
    int n, m;
    cin >> n >> m;
    cin >> (s + 1) >> (t + 1);
    sort(t + 1, t + m + 1);
    int p = 1, q = 1;
    while(p <= n && q <= m)
    {
        if(s[p] <= t[q])
            cout << s[p++];
        else
            cout << t[q++];
    }
    while(p <= n)
        cout << s[p++];
    while(q <= m)
        cout << t[q++];
    cout << "\n";
    return 0;
}

數位翻轉

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

long long dp[1005][1005][2];
int a[1005], b[1005];

int f(int x)
{
    int r = 0;
    while(x)
    {
        r = (r << 1) | (x & 1);
        x >>= 1;
    }
    return r;
}

int main()
{
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        b[i] = f(a[i]);
    }
    
    for(int i = 1; i <= n; i++)
    {
        dp[i][0][0] = dp[i - 1][0][0] + a[i];
        for(int j = 1; j <= m; j++)
        {
            dp[i][j][0] = max(dp[i - 1][j][0] + a[i], dp[i - 1][j][1] + a[i]);
            dp[i][j][1] = max(dp[i - 1][j][1] + b[i], dp[i - 1][j - 1][0] + b[i]);
        }
    }
    
    cout << max(dp[n][m][0], dp[n][m][1]) << "\n";
    
    return 0;
}

數星星

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

const ll mod = 1e9 + 7;

int n, d[100005], L, R;
ll fac[100005], inv[100005];
ll f[100005];

ll qpow(ll a, ll n)
{
    ll r = 1;
    while(n)
    {
        if(n & 1)
            r = r * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return r;
}

ll getC(int n, int m)
{
    if(n < 0 | m < 0 || n < m)
        return 0;
    return fac[n] * inv[m] % mod * inv[n - m] % mod;
}

int main()
{
    cin >> n;
    for(int i = 1; i < n; i++)
    {
        int a, b;
        cin >> a >> b;
        d[a]++;
        d[b]++;
    }
    cin >> L >> R;
    
    fac[0] = 1;
    for(int i = 1; i <= n; i++)
        fac[i] = fac[i - 1] * i % mod;
    inv[n] = qpow(fac[n], mod - 2);
    for(int i = n - 1; i >= 0; i--)
        inv[i] = inv[i + 1] * (i + 1) % mod;
    
    ll ans = 0;
    if(L == 1 && L <= R)
    {
        ans += n;
        L++;
    }
    if(L == 2 && L <= R) // 這個特判也許是易錯點?兩點組成的圖不能重複計算
    {
        ans += n - 1;
        L++;
    }
    
    for(int i = L - 1; i <= n; i++)
    {
//        for(int j = L; j <= R; j++)
//            f[i] = (f[i] + getC(i, j - 1)) % mod;
        f[i] = ((f[i - 1] * 2 - getC(i - 1, L - 1) - getC(i - 1, R - 1) + getC(i, L - 1)) % mod + mod) % mod; // 楊輝三角公式遞推
    }
    // f[i] 表示菊花圖中間點的度數為 i 時的方案總數
    
    for(int i = 1; i <= n; i++)
        ans = (ans + f[d[i]]) % mod;
    cout << ans << "\n";
    
    return 0;
}

套手鐲

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;

int N, W, H;
int x[1005], y[1005], r[1005];
vector<int> xpool;
int ans;

int tr[1005], maxn;
int lowbit(int x)
{
    return x & -x;
}
void update(int p, int v)
{
    while(p <= maxn)
    {
        tr[p] += v;
        p += lowbit(p);
    }
}
int query(int p)
{
    int r = 0;
    while(p)
    {
        r += tr[p];
        p -= lowbit(p);
    }
    return r;
}
void initBIT(int n)
{
    maxn = n;
    while(n)
        tr[n--] = 0;
}

void solve()
{
    for(int &L : xpool)
    {
        int R = L + W;
        vector<pii> line;
        vector<int> ypool;
        
        for(int i = 1; i <= N; i++)
            if(x[i] - r[i] >= L && x[i] + r[i] <= R)
            {
                line.push_back(pii(y[i] - r[i], y[i] + r[i]));
                ypool.push_back(y[i] + r[i]);
            }
        
        sort(line.begin(), line.end());
        
        sort(ypool.begin(), ypool.end());
        ypool.erase(unique(ypool.begin(), ypool.end()), ypool.end());
        
        initBIT(ypool.size());
        for(pii &l : line)
            update(lower_bound(ypool.begin(), ypool.end(), l.second) - ypool.begin() + 1, 1);
        
        for(pii &l : line)
        {
            int p = upper_bound(ypool.begin(), ypool.end(), l.first + H) - ypool.begin();
//             if(p == 0)
//                continue;
            ans = max(ans, query(p));
            update(lower_bound(ypool.begin(), ypool.end(), l.second) - ypool.begin() + 1, -1);
        }
    }
}

int main()
{
    cin >> N >> W >> H;
    for(int i = 1; i <= N; i++)
    {
        cin >> x[i] >> y[i] >> r[i];
        xpool.push_back(x[i] - r[i]);
    }
    
    sort(xpool.begin(), xpool.end());
    xpool.erase(unique(xpool.begin(), xpool.end()), xpool.end());
    
    solve();
    swap(W, H);
    solve();
    
    cout << ans << "\n";
    
    return 0;
}

跳石頭

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

int n, c[40005];
bitset<40005> bs[40005];

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
        cin >> c[i];
    int ans = 0;
    for(int i = n; i >= 1; i--)
    {
        bs[i].set(c[i]);
        if(i + c[i] <= n)
            bs[i] |= bs[i + c[i]];
        if(i * 2 <= n)
            bs[i] |= bs[i * 2];
        ans = max(ans, (int)bs[i].count());
    }
    cout << ans << "\n";
    
    return 0;
}

最長迴文前字尾

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

int solve(string &s)
{
    int len = s.size();
    int ans = 0, tmp = 0;
    int j = len - 1;
    for(int i = 0; i < j; i++)
    {
        if(s[i] == s[j])
        {
            j--;
            tmp++;
            ans = max(ans, tmp);
        }
        else
        {
            j = len - 1;
            tmp = 0;
            if(s[i] == s[j]) // 當前雖然失配,但可能和第一個位置是匹配的
            {
                j--;
                tmp++;
                ans = max(ans, tmp);
            }
        }
    }
    tmp = 0, j = len - 1;
    reverse(s.begin(), s.end());
    for(int i = 0; i < j; i++)
    {
        if(s[i] == s[j])
        {
            j--;
            tmp++;
            ans = max(ans, tmp);
        }
        else
        {
            j = len - 1;
            tmp = 0;
            if(s[i] == s[j])
            {
                j--;
                tmp++;
                ans = max(ans, tmp);
            }
        }
    }
    return ans;
}

int main()
{
    string s;
    cin >> s;
    
    int l = 0, r = s.size() - 1;
    while(l < r && s[l] == s[r])
        l++, r--;
    
    if(l >= r)
        cout << l << "\n";
    else
    {
        s = s.substr(l, r - l + 1);
        cout << l + solve(s) << "\n";
    }
    return 0;
}

相關文章