Loading

【题解】Atcoder Beginner Contest 443(ABC443) A~E

A - Append s

模拟即可。

#include<bits/stdc++.h>
using namespace std;
string s;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>s;
    cout<<s<<'s';
    return 0;
}

B - Setsubun

暴力计算每过一年后的豆子数,直到达标。

#include<bits/stdc++.h>
using namespace std;
int n,k,sum,ans;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>k;
    while(sum<k){
        sum+=n;
        ans++;
        n++;
    }
    cout<<ans-1;
    return 0;
}

C - Chokutter Addiction

如果两次检查时间间隔 \(\ge100\),则答案 \(+A_i-A_{i-1}-100\)

如果 \(<100\),相当于没有检查,还按间隔 \(\ge100\) 的那次检查计算答案。

最后把剩下时间也算进去。最后一次检查过 \(100\) 后的时间都算上。

注意特判 \(n=0\) 的情况。

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int n,T,ans;
int a[N],t;
bool flag=1;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>T;
    if(!n){
        cout<<T;
        return 0;
    }
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(i==1) ans+=a[i],t=a[i];
        else if(a[i]-t>100) ans+=a[i]-t-100,t=a[i];
    } 
    ans+=max(0,T-t-100);
    cout<<ans;
    return 0;
}

D - Pawn Line

只能减小 \(R_i\) 的值,最小的 \(R_i\) 肯定是不能动的。所以每个 \(R_i\) 是有其上界的,取决于最小的 \(R_i\)

每个元素两侧都最多比该元素大 \(1\),这是取值上界,如果已经合法就不用管,不合法,减到上界所需操作次数最小。

处理出每个 \(R_i\) 的上界,与原 \(R_i\) 做差。

只需要从两侧各扫一遍,就能处理出每个元素的上界。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10;
int T,n;
int r[N],sum;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        cin>>n;
        sum=0;
        for(int i=1;i<=n;i++){
            cin>>r[i];
            sum+=r[i];
        }
        for(int i=2;i<=n;i++) r[i]=min(r[i],r[i-1]+1);
        for(int i=n-1;i>=1;i--) r[i]=min(r[i],r[i+1]+1);
        for(int i=1;i<=n;i++) sum-=r[i];
        cout<<sum<<'\n';
    }
    return 0;
}

E - Climbing Silver

注意到运动情况:每次必须向上一行,左中右三列自选。

因此,可能达到的格子就是一个扇形,顶点是第 \(n\) 行,向上每一行左右各拓宽一列。

考虑一个 \(O(n^2)\) DP。从第 \(n\) 行开始一行行向上扫,处理出每个格子是否可以到达,可到达为 \(1\),不可达为 \(0\)\(f_{i,j}\) 可由 \(f_{i+1,j-1},f_{i+1,j},f_{i+1,j+1}\) 转移而来。

对于一个空地,三者有任意为 \(1\) 的格子就可以到达。对于一个墙,三者有任意为 \(1\),且此列向下没有不可到达的墙才可达。因此维护一个标记数组,记录每一列此前是否有不可达的墙。

DP 的初始化,第 \(n\) 行仅起点可达,并为第 \(n\) 行的所有墙所在列打上标记。

#include<bits/stdc++.h>
using namespace std;
const int N=3010;
int T,n,c;
int G[N][N],f[N][N];
bool flag[N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        cin>>n>>c;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                char s;
                cin>>s;
                if(s=='#') G[i][j]=1;
                else G[i][j]=0;
                f[i][j]=0;
                flag[j]=0;
            }
        }
        f[n][c]=1;
        for(int i=1;i<=n;i++) if(G[n][i]) flag[i]=1;
        for(int i=n-1;i>=1;i--){
            for(int j=1;j<=n;j++){
                if(G[i][j]){
                    if(!flag[j]&&(f[i+1][j-1]||f[i+1][j]||f[i+1][j+1])) f[i][j]=1;
                    else flag[j]=1;
                }else{
                    if(f[i+1][j-1]||f[i+1][j]||f[i+1][j+1]) f[i][j]=1;
                }
            }
        }
        for(int i=1;i<=n;i++) cout<<f[1][i];
        cout<<'\n';
    }
    return 0;
}
posted @ 2026-02-01 19:32  Seqfrel  阅读(5)  评论(1)    收藏  举报