【做题纪要】ABC351

【做题纪要】ABC351

昨天ABC打了三道题就去看别人颓了,也是喜提 \(\text{-20 rated}\)

不懂,就我这棕色的名字还能扣 \(\text{rated}\) 吗?早知道认真打了

特别感谢:文心一言对于题目的翻译支持

A - The bottom of the ninth

  • 题意

    高桥队和青木队正在进行一场棒球比赛,高桥队首先进行击球。

    目前,比赛已经完成了前九局的上半场,即将开始第九局的下半场。

    得分情况如下:

    • 高桥队在第 \(i\) 局(\(1 \leq i \leq 9\))的上半场得了 \(A_i\) 分。
    • 青木队在第 \(j\) 局(\(1 \leq j \leq 8\))的下半场得了 \(B_j\) 分。

    在第九局上半场结束时,高桥队的得分不少于青木队的得分。

    现在,我们需要确定青木队在第九局下半场至少需要得到多少分才能赢得比赛。

    注意:如果第九局下半场结束时双方得分相同,则比赛以平局结束。因此,青木队要想获胜,必须在第九局下半场结束时得分严格高于高桥队。

    在任何时候,高桥队的得分是到目前为止所有上半局得分的总和,青木队的得分是所有下半局得分的总和。

  • 思路

    把上面的加起来,然后减去下面的每一个

    最后只要输出减去的结果再加上 \(1\) 即可

  • 代码

    inline void In(){
        int ans1=0,ans2=0;
        for_(i,1,9){
            int x;
            std::cin >> x;
            ans1+=x;
        }
        for_(i,1,8){
            int x;
            std::cin >> x;
            ans2+=x;
        }
        std::cout << ans1 - ans2 + 1 <<std::endl;
    }
    

B - Spot the Difference

  • 题意

    给定两个网格,每个网格都有N行和N列,分别称为网格A和网格B。

    每个网格的单元格中包含一个小写英文字母。

    网格A中第i行第j列的字符是 \(A_{i,j}\)

    网格B中第i行第j列的字符是 \(B_{i,j}\)

    这两个网格仅在一个单元格中有所不同。也就是说,存在恰好一对正整数\((i, j)\)(其中\(i\)\(j\)均不大于N),使得 \(A_{i,j} \neq B_{i,j}\)。请找出这一对\((i, j)\)

  • 思路

    按照题意模拟,找到不同的直接退出即可

  • 代码

    char A[105][105],B[105][105];
    inline void In(){
        int n;
        std::cin >> n;
        for_(i,1,n){
            for_(j,1,n){
                std::cin >> A[i][j];
            }
        }
        for_(i,1,n){
            for_(j,1,n){
                std::cin >> B[i][j];
                if(B[i][j]!=A[i][j]){
                    std::cout << i << " " << j << std::endl;
                    return;
                }
            }
        }
    }
    

C - Merge the balls

  • 题意

    你有一个空的序列和 \(N\) 个球。第 \(i\) 个球(\(1 \leq i \leq N\))的大小是 \(2^{A_i}\)

    你将进行 \(N\) 次操作。

    在第 \(i\) 次操作中,你将第 \(i\) 个球添加到序列的右端,并重复以下步骤:

    1. 如果序列中只有一个或更少的球,结束操作。

    2. 如果序列中最右边的球和第二右边的球大小不同,结束操作。

    3. 如果序列中最右边的球和第二右边的球大小相同,移除这两个球,并在序列的右端添加一个大小等于这两个移除的球的大小之和的新球。然后,回到步骤 \(1\) 并重复这个过程。

    确定在 \(N\) 次操作后序列中剩余的球的数量。

  • 思路

    按照题意模拟即可

  • 代码

    std::stack<int> STA;
    int A[N];
    inline void In(){
        int n;
        std::cin >> n;
        for_(i,1,n){
            std::cin >> A[i];
            int ans = A[i];
            while( (!STA.empty()) && (STA.top()==ans) ){
                ans += 1;
                STA.pop();
            }  
            STA.push(ans);
        }
        std::cout << STA.size() ;
        
    }
    

D - Grid and Magnet

  • 题意

    有一个 \(H\)\(W\) 列的网格。一些单元格(可能为零个)包含磁铁。

    网格的状态由 \(H\) 个长度为 \(W\) 的字符串 \(S_1​,S_2​,…,S_H\) ​表示。如果 \(S_i\) ​的第 \(j\) 个字符是 #,则表示从上数第 \(i\) 行从左数第 \(j\) 列的单元格中存在一个磁铁。如果是 .,则表示该单元格为空。

    高桥君穿着铁制盔甲,可以在网格中按以下方式移动:

    1. 如果当前单元格的垂直或水平相邻单元格中有任何磁铁,他都无法移动。

    2. 否则,他可以移动到任何垂直或水平相邻的单元格。

      但是,他不能离开网格。

    对于每个没有磁铁的单元格,定义其自由度为从该单元格出发通过反复移动可以到达的单元格数量。找出网格中所有没有磁铁的单元格中的最大自由度。

    在自由度的定义中,“通过反复移动可以到达的单元格”意味着可以通过一系列移动(可能为零次移动)从初始单元格到达的单元格。没有必要从初始单元格开始存在一条可以访问所有这样的可达单元格的移动序列。具体来说,每个单元格本身(没有磁铁)总是包含在从该单元格可达的单元格中。

  • 思路

    暴力 \(\text{BFS}\) 即可

  • 代码

    点击查看代码
    const int di[] = {-1, 0, 1, 0};
    const int dj[] = {0, 1, 0, -1};
    
    inline void In(){
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout.tie(nullptr);
    
        int H, W;
        std::cin >> H >> W;
        
        std::vector<std::string> s(H);
        for_(i,0,H-1) 
            std::cin >> s[i];
        
        std::vector x(H, std::vector<bool>(W));
        for_(i,0,H-1){
            for_(j,0,W-1) {
                if (s[i][j] != '#') 
                    continue;
    
                x[i][j] = true;
                
                for_(v,0,3) {
                    int ni = i+di[v], nj = j+dj[v];
                    if (ni < 0  || ni >= H || nj < 0 || nj >= W) 
                        continue;
    
                    x[ni][nj] = true;
                }
            }
        }
        int ans = 1;
        std::vector used(H, std::vector<bool>(W));
        std::vector last(H, std::vector<int>(W)); int tm = 0;
        for_(si,0,H-1){
            for_(sj,0,W-1) {
                if (x[si][sj]) 
                    continue;
                
                if (used[si][sj]) 
                    continue;
                
                ++tm;
                int cnt = 0;
                std::queue< std::pair<int, int> > q;
                q.emplace(si, sj); 
                used[si][sj] = true;
    
                while (q.size()){
                    auto [i, j] = q.front(); 
                    q.pop();
                    
                    cnt+=1;
                    for_(v,0,3){
                        int ni = i+di[v], nj = j+dj[v];
                        
                        if (ni < 0 || ni >= H || nj < 0 || nj >= W) 
                            continue;
                        
                        if (used[ni][nj]) 
                            continue;
                        
                        if (x[ni][nj]) {
                            if (last[ni][nj] != tm) {
                                cnt+=1, 
                                last[ni][nj] = tm;
                            }
                            continue;
                        }
                        
                        q.emplace(ni, nj);
                        used[ni][nj] = true;
                    }
                }
                ans = std::max(ans, cnt);
            }
        }
        std::cout << ans << '\n';
    }
    

翻译,给出MarkDown原码,数学部分使用LaTeX格式

E - Jump Distance Sum

  • 题意

    在坐标平面上有 \(N\) 个点 \(P_1, P_2, \ldots, P_N\),其中点 \(P_i\) 的坐标为 \((X_i, Y_i)\)

    两点 \(A\)\(B\) 之间的距离 \(\text{dist}(A, B)\) 定义如下:

    1. 一只兔子最初在点 \(A\)
    2. 兔子在位置 \((x, y)\) 可以跳到 \((x+1, y+1)\)\((x+1, y-1)\)\((x-1, y+1)\),或 \((x-1, y-1)\) 中的一个位置。
    3. \(\text{dist}(A, B)\) 定义为从点 \(A\) 到点 \(B\) 所需的最小跳跃次数。
    4. 如果经过任意次数的跳跃后,无法从点 \(A\) 到达点 \(B\),则令 \(\text{dist}(A, B) = 0\)

    计算求和:

    \[\sum_{i=1}^{N-1} \sum_{j=i+1}^{N} \text{dist}(P_i, P_j) \]

  • 思路

    赛时没有想出来,放一份官方题解的翻译

    将平面以原点为中心旋转 \(45\)度,并缩放 \(\sqrt 2\) 倍。这样,原本位于\((X,Y)\)的点将移动到 \((X+Y,X-Y)\)

    \((x_i, y_i)\) 为每个点 \(P_i\) 经过此变换后的坐标。那么,\(x_i = X_i + Y_i\)\(y_i = X_i - Y_i\)

    接下来,我们考虑 \(\text{dist}(A,B)\) 的定义如何变化。

    在原始定义中,兔子可以从 \((X,Y)\) 跳到 \((X+1,Y+1)\)\((X+1,Y-1)\)\((X-1,Y+1)\),和 \((X-1,Y-1)\);因此,经过变换后,它可以从 \((X+Y,X-Y)\) 跳到 \((X+Y+2,X-Y)\)\((X+Y,X-Y+2)\)\((X+Y,X-Y-2)\),和 \((X+Y-2,X-Y)\)

    \(x = X + Y\)\(y = X - Y\) 替换,兔子可以从 \((x,y)\) 跳到 \((x+2,y)\)\((x,y+2)\)\((x,y-2)\),和 \((x-2,y)\)

    \(A\)\(B\) 所需的最小跳跃次数定义了 \(\text{dist}(A,B)\)(如果无法达到则为 \(0\) )。

    此后,我们考虑变换后的问题。即,我们令 \(P_i = (x_i, y_i)\),定义 \(\text{dist}(A,B)\),并考虑根据前面定义的 \(\text{dist}(A,B)\),计算 \(\sum\limits_{i=1}^{N-1} \sum\limits_{j=i+1}^{N} \text{dist}(P_i, P_j)\)的和。

    显然,这将得到与原始定义相同的答案。

    我们进一步考虑对于 \(A = (x_1, y_1)\)\(B = (x_2, y_2)\)\(\text{dist}(A,B)\)。如果 \(x_1 \not\equiv x_2 \pmod{2}\)\(y_1 \not\equiv y_2 \pmod{2}\),则兔子无法从 \(A\) 跳到 \(B\),所以 \(\text{dist}(A,B) = 0\)。否则,它等于曼哈顿距离的一半,即 \(\frac{1}{2}(|x_1 - x_2| + |y_1 - y_2|)\)

posted @ 2024-05-08 21:04  Vsinger_洛天依  阅读(30)  评论(0编辑  收藏  举报