ABC398题解

A - Doors in the Center

问题陈述

找出满足以下所有条件的长度为 \(N\) 的字符串:

  • 每个字符都是 -=
  • 它是一个回文字符串。
  • 正好包含一个或两个 =。如果包含两个 =,它们是相邻的。

这样的字符串是唯一的。

解题思路

简单构造题,把 '=' 构造到中间即可,偶数时放两个,奇数时放一个。

AC代码

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

int n;

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    cin>>n;
    if(n&1){
        for(int i = 1;i <= n/2;i++)cout<<'-';
        cout<<'=';
        for(int i = 1;i <= n/2;i++)cout<<'-';
    }
    else
    {
        for(int i = 1;i <= n/2-1;i++)cout<<'-';
        cout<<"==";
        for(int i = 1;i <= n/2-1;i++)cout<<'-';
    }
	return 0;
}

B - Full House 3

问题陈述

我们有七张牌。 \(i\) -th 牌 \((i=1,\ldots,7)\) 上面写着一个整数 \(A_i\)
请判断是否有可能从这七张牌中选择五张,使所选的牌组成葫芦。

当且仅当满足以下条件时,一组五张牌被称为葫芦:

  • 对于不同的整数 \(x\)\(y\) ,有三张 \(x\) 和两张 \(y\)

解题思路

开桶暴力统计即可,一定要先找\(\geq 3\)的,不然会被重复数。

AC代码

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

int a[8],cnt[15];

bool flag3 , flag2;

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    for(int i = 1;i <= 7;i++)cin>>a[i];
    for(int i = 1;i <= 7;i++)cnt[a[i]]++;
    bool flag = 0;
    for(int i = 1;i <= 14;i++){
        if(cnt[i] >= 3){
            for (int j = 1; j <= 14; j++) {
                if (i != j && cnt[j] >= 2) {
                    flag = true;
                    break;
                }
            }
            if(flag)break;
        }
    }
    if(flag){
        cout<<"Yes";
    }else{
        cout<<"No";
    }
	return 0;
}

C - Uniqueness

问题陈述

\(N\) 个人,标记为 \(1\)\(N\) 。人 \(i\) 有一个整数 \(A_i\)

在满足 "其他 \(N-1\) 人中没有一个人的整数与自己相同 "条件的人中,找出整数最大的那个人,并打印这个人的标签。

如果没有人满足条件,则报告这一事实。

解题思路

开个结构体然后用\(map\)暴力统计,把计数为\(1\)的元素放到新数组,找到新数组中的最大值,输出原下标即可。

AC代码

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline
#define inf 0x3f3f3f3f

using namespace std;
using ll = long long;
using ull = unsigned long long;

const int maxn = 3e5+10;

int n;
int a1[maxn];
int cnt;

map<int,int> mp;

struct node{
    int id,v;
}a[maxn];

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    cin>>n;
    for(int i = 1;i <= n;i++){
        cin>>a1[i];
        mp[a1[i]]++;
    }
    for(int i = 1;i <= n;i++){
        if(mp[a1[i]] == 1){
            a[++cnt] = {i,a1[i]};
        }
    }
    int ans = -inf;
    int res;
    for(int i = 1;i <= cnt;i++){
        if(a[i].v > ans){
            ans = a[i].v;
            res = a[i].id;
        }
    }
    if(ans == -inf){
        cout<<-1;
        return 0;
    }
    cout<<res;
	return 0;
}

D - Bonfire

问题陈述

有一个无限大的二维网格,在坐标 \((0,0)\) 处有一堆篝火。
在时间 \(t=0\) ,只有单元格 \((0,0)\) 存在烟雾。

给你一个长度为 \(N\) 的字符串 \(S\) ,由 "N"、"W"、"S"、"E "组成。在 \(t=1,2,\dots,N\) 时刻,会依次发生以下情况:

  • 风吹起,当时存在的所有烟雾按如下方式移动:
    • 如果 \(S\)\(t\) -th 字符是 "N", \((r,c)\) 单元格中的烟雾会移动到 \((r-1,c)\) 单元格。
    • 如果是 "W", \((r,c)\) 单元格中的烟雾会移动到 \((r,c-1)\) 单元格。
    • 如果是 "S", \((r,c)\) 单元格中的烟雾会移动到 \((r+1,c)\) 单元格。
    • 如果是 "E", \((r,c)\) 单元格中的烟雾会移动到 \((r,c+1)\) 单元格。
  • 如果单元格 \((0,0)\) 中没有烟雾,则会在单元格 \((0,0)\) 中产生新的烟雾。

高桥站在 \((R,C)\) 单元格。
对于每个整数 \(1 \le t \le N\) ,判断在时间 \(t+0.5\) 时,单元格 \((R,C)\) 是否存在烟雾,并按照要求的格式打印响应。

解题思路

对于每次更改当成更改原点,用\(unordered_set\)统计即可。

AC代码

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

ll n,r,c,dx,dy;
string s;
unordered_set<ll> vis;

il ll hs(ll x,ll y){return x << 32 | (y & 0xffffffffll);}

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    cin>>n>>r>>c>>s;
    vis.insert(hs(0, 0));
    string res;
    for (char a : s) {
        switch (a) {
            case 'N': {dx--; break;}
            case 'S': {dx++; break;}
            case 'W': {dy--; break;}
            case 'E': {dy++; break;}
        }
        ll key = hs(dx - r, dy - c);
        res += vis.count(key) ? '1' : '0';
        vis.insert(hs(dx, dy));
    }
    cout << res;
    return 0;
}

E - Tree Game

问题陈述

这个问题是一个交互式问题(在这个问题中,你的程序和法官系统通过输入和输出进行交流)。

给你一棵树 \(G\) ,其中有 \(N\) 个顶点,编号为 \(1\)\(N\)\(i\) 这条边连接着顶点 \(U_i\)\(V_i\)

你们将用这棵树 \(G\) 与高桥玩一个游戏。首先,你们决定谁是第一名,谁是第二名。然后,从第一位玩家开始,轮流进行以下操作:

  • 选择一对满足以下两个条件的整数 \((i,j)\)\(1 \leq i &lt; j \leq N\) ,然后添加一条连接顶点 \(i\)\(j\)\(G\) 的边。
    • \(G\) 中没有连接顶点 \(i\)\(j\) 的边。
    • 添加一条连接顶点 \(i\)\(j\) 的边不会产生奇循环。

无法进行此操作的棋手输棋,而另一方棋手赢棋。请与高桥先生下这盘棋并获胜。

什么是奇数循环?

当且仅当满足以下所有条件时, \(G\) 的顶点 \((v_0,v_1,\ldots,v_k)\) 序列称为奇数循环:

  • \(k\) 是奇数。
  • \(v_0=v_k\) .
  • 对于每一个 \(1\leq i \leq k\) ,都有一条边连接 \(v_{i-1}\)\(v_{i}\)

解题思路

二分图染色后模拟。

AC代码

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

const int maxn = 105;
const int maxm = 2e4+10;

int color[maxn];
set<pair<int, int>> e,e2,e3;
bool flag;
int k,i,j;

struct E {
    int to, next;
} Edge[maxm];

int tot, Head[maxn];

inline void add(int u, int v) {
    Edge[tot].to = v;
    Edge[tot].next = Head[u];
    Head[u] = tot++;
}

void dfs(int u, int c) {
    color[u] = c;
    for (int i = Head[u];~i;i = Edge[i].next) {
        int v = Edge[i].to;
        if (color[v] == -1) {
            dfs(v, 1 - c);
        }
    }
}

il void solve()
{
    if (flag) {
        while(1){
            if (e3.empty()) break;
            auto it = e3.begin();
            pair<int, int> ee = *it;
            cout << ee.first << " " << ee.second << endl;
            e3.erase(it);
            cin >> i >> j;
            if (i == -1 && j == -1) return;
            if (i > j) swap(i, j);
            e3.erase({i, j});
        }
    } else {
        while (1) {
            cin >> i >> j;
            if (i == -1 && j == -1) return;
            if (i > j) swap(i, j);
            e3.erase({i, j});
            if (e3.empty()) break;
            auto it = e3.begin();
            cout << it->first << " " << it->second << endl;
            e3.erase(it);
        }
    }
}

int main() {
    // freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	// ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    int n;cin >> n;
    memset(Head,-1, sizeof(Head));
    memset(color,-1, sizeof(color));
    for (int i = 0; i < n - 1; ++i) {
        int u, v;cin>>u>>v;
        add(u, v);add(v, u);
        if(u > v) swap(u, v);
        e.insert({u, v});
    }
    dfs(1, 0);
    for (int i = 1; i <= n; ++i) {
        for (int j = i + 1; j <= n; ++j) {
            if (color[i] != color[j]) {
                auto edge = (i < j) ? make_pair(i, j) : make_pair(j, i);
                if (e.find(edge) == e.end())e2.insert(edge);
            }
        }
    }
    k = e2.size();
    flag = 0;
    if (k == 0) {
        cout<<"Second"<<endl;
        return 0;
    } else {
        if (k & 1) {
            cout<<"First"<<endl;
            flag = 1;
        } else {
            cout<<"Second"<<endl;
        }
    }
    e3 = e2;
    solve();
    return 0;
}

F - ABCBA

问题陈述

找出一个以 \(S\) 为前缀的最短回文。

解题思路

KMP的拓展应用题,用Manacher也能当板子做,找最小循环节就好。

AC代码

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline

using namespace std;
using ll = long long;
using ull = unsigned long long;

int main(){
	// freopen("test.in","r",stdin);
	// freopen("test.out","w",stdout);
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
    string s;cin>>s;
    int n = s.size();
    string sr(s.rbegin(), s.rend());
    string s2 = sr + '#' + s;
    int m = s2.size();
    vector<int> p(m, 0);
    for (int i = 1; i < m; ++i) {
        int j = p[i-1];
        while (j > 0 && s2[i] != s2[j])j = p[j-1];
        if (s2[i] == s2[j])j++;
        p[i] = j;
    }
    int k = p.back();
    string add = s.substr(0, n - k);
    reverse(add.begin(), add.end());
    string ans = s + add;
    cout<<ans;
    return 0;
}
posted @ 2025-03-22 21:49  Zheng_iii  阅读(179)  评论(0)    收藏  举报