AtCoder Beginner Contest 334 ABCDE

nannandbk / 2024-02-04 / 原文

AtCoder Beginner Contest 334](https://atcoder.jp/contests/abc334) ABCDE

A - Christmas Present

签到不多说。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int a,b; cin>>a>>b;
    cout<<(a>b?"Bat":"Glove")<<"\n";


    return 0;
}

B - Christmas Trees

题意:给你 \(A,M,L,R\) ,表示在一个坐标轴上,对于任意的整数 \(k\) ,在 \(A+kM\) 的位置都种上了圣诞树,现问你 \([L,R]\) 的区间内有多少圣诞树?

思路:分类讨论,考虑\(A\)和区间\([L,R]\)的关系。

  1. 如果\(A\)\([L,R]\)之间(\(L \le A \le R\))。

    \(res = (A-L)/M + (R-A)/M +1\) (+1是因为k可以等于0)

  2. \(A\)在区间\([L,R]\)左边(\(A<L\))。

    前缀和思想,\(pre[R]-pre[L-1]\)

    \(res = (R-A)/M - ((L-1)-A)/M\)

  3. \(A\)在区间\([L,R]\)右边边(\(A>R\))。

    \(pre[L]-pre[R+1]\)

\(res = (A-L)/M - (A-(R+1))/M\)

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    ll a,m,l,r; cin>>a>>m>>l>>r;

    ll res = 0;
    if(a < l)
    {
        res = (r-a)/m - ((l-1)-a)/m;
    }
    else if(l <= a && a <= r)
    {
        res = (r-a)/m + (a-l)/m + 1;
    }
    else if(a > r)
    {
        res = (a-l)/m - (a-(r+1))/m;
    }
    cout<<res<<"\n";

    return 0;
}

C - Socks 2

题意:高桥君有 \(N\) 双袜子,第 \(i\) 双袜子的编号是 \(i\) ,有一天他突然意识到了自己丢失了 \(K\) 只袜子,我们定义两只袜子的 “差异度” 为这两只袜子编号的差的绝对值。

现给你这 \(K\) 只袜子的编号,把剩余的 \(2N-K\) 只袜子两两配对,求配对后差异度和的最小值。注意到如果 \(K\) 是奇数,配对后剩余一只袜子是允许的,且不算入差异度的计算中。

第一行输入 \(N,K\),第二行输入 \(K\) 个数表示丢失的袜子的编号。

思路:思考怎么样差异度最小,肯定是排序之后相邻两个配对是最优的。

那么如果是偶数个之间两两配对即可。如果是奇数个呢?有一个是多出来的,那么是哪一个呢?不知道,我们考虑对前后缀都做一次前缀/后缀和,枚举是哪一个不要,答案取min就行了。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 5e5 + 10;
int a[N],cnt;
ll pre[N],suf[N],res;
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int n,k; cin>>n>>k;
    set<int>s;
    vector<int>v;
    for(int i = 1;i <= k; i++)
    {
        int x; cin>>x;
        s.insert(x);
    }
    for(int i = 1;i <= n; i++)
    {
        a[++cnt] = i;
        if(s.find(i) == s.end())
            a[++cnt] = i;
    }
    int m = 2*n-k;
    // for(int i = 1;i <= m; i++)
    //     cout<<a[i]<<" ";
    // cout<<"\n";
    for(int i = 1;i <= m; i += 2)
    {
        pre[i] = pre[i-1] + abs(a[i]-a[i+1]);
        pre[i+1] = pre[i];                         
    }

    for(int i = m;i >= 1; i -= 2)
    {
        suf[i] = suf[i+1] + abs(a[i]-a[i-1]);
        suf[i-1] = suf[i];
    }

    if(m % 2 == 0){
        res = pre[m];
    }else{
        res = 1e9;
        for(int i = 1;i <= m; i++)
        {
            res = min(res,pre[i-1]+suf[i+1]);
        }
    }
    cout<<res<<"\n";
    return 0;
}

D - Reindeer and Sleigh

题意:有 \(N\) 个雪橇,其中第 \(i\) 个雪橇需要 \(R_i\) 匹驯鹿来拉。每匹驯鹿最多拉一个雪橇。现有 \(Q\) 次询问,每次询问给你 \(X\) ,问你如果有 \(X\) 匹驯鹿,最多能拉多少个雪橇?

第一行输入 \(N,Q\),第二行输入 \(R_i\),接下来每行输入一个询问。

思路:排序+二分。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
ll need[N],s[N];

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int n,q; cin>>n>>q;

    for(int i = 1;i <= n; i++)
        cin>>need[i];
    sort(need+1,need+1+n);
    for(int i = 1;i <= n; i++)
        s[i] = s[i-1]+need[i];
 
    for(int tc = 1;tc <= q; tc++)
    {
        ll x;  cin>>x;
        ll l = 0, r = n;
        while(l<=r)
        {
            ll mid = (l+r)>>1;
            if(s[mid] <= x)l = mid+1;
            else r = mid-1;
        }
        cout<<l-1<<"\n";
    }

    return 0;
}

E - Christmas Color Grid 1

题意:给定 \(n\times m\) 的字符矩阵,# 表示绿色,. 表示红色。

均匀随机一个红色块换成绿色,求绿色四连通块的期望数量,对 \(998244353\) 取模。

\(1\le n,m\le 1000\)

题意:先用\(dfs\)分块,每个连通块标号。然后我们for一边,遇到每一个\(.\)去看它的四个方向有几种连通块,如果有的话就加上\(max(0,原来的连通块数-这个\).\(四个方向上的连通块种类数+1)\)。取max是因为可能这个点四周没有连通块,防止是负数。那么如果四周没有连通块的话答案加上\(原连通块数+1\)。最后的话用除法逆元求答案即可。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int mod = 998244353;
const int N = 2e5 + 10;
ll n,m,hav;
int cnt = 1;
char a[1010][1010];
int b[1010][1010];
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
bool in(int x,int y)
{
    return x >= 1 && x <= n && y >= 1 && y <= m;
}
void dfs(int x,int y,int num)
{
    b[x][y] = num;
    for(int i = 0;i < 4; i++)
    {
        int tx = x + dir[i][0];
        int ty = y + dir[i][1];
        if(in(tx,ty) && a[tx][ty]=='#' && !b[tx][ty])
        {
            dfs(tx,ty,num);
        }
    }
}
ll qmi(ll a, ll b, ll mod)
{
    ll ans = 1 % mod;
    while(b)
    {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}

signed main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    cin>>n>>m;
    for(int i = 1;i <= n; i++)
        for(int j = 1;j <= m; j++)
            cin>>a[i][j];

    for(int i = 1;i <= n; i++)
        for(int j = 1;j <= m; j++)if(a[i][j]=='#' && !b[i][j]){
            dfs(i,j,cnt);
            cnt++,hav++;
        }

    // for(int i = 1;i <= n; i++)
    // {
    //     for(int j = 1;j <= m; j++)
    //     {
    //         cout<<a[i][j];
    //     }
    //     cout<<"\n";
    // }
    ll cnt = 0,ans = 0;
    for(int i = 1;i <= n; i++)
    {
        for(int j = 1;j <= m; j++)
        {
            if(a[i][j]=='.')
            {
                cnt++;
                set<ll>s;
                int d = 0;
                for(int k = 0;k < 4; k++)
                {
                    int tx = i + dir[k][0];
                    int ty = j + dir[k][1];
                    if(in(tx,ty)&&a[tx][ty] != '.')s.insert(b[tx][ty]);
                    if(in(tx,ty) && a[tx][ty]=='.')d++;
                }
                if(s.size() == 0 && d)ans++;
               // cout<<"s.size() = "<<s.size()<<"\n";
                // for(auto x : s)
                //     cout<<x<<" ";
                // cout<<"\n";
                // cout<<"!!"<<hav-(s.size()-1)<<"\n";
                ans += hav-max(0ll,(ll)s.size()-1);

            }
        }
    }
    ll g = __gcd(ans,cnt);
     // cout<<"hav = "<<hav<<"\n";
     // cout<<"ans = "<<ans<<" cnt = "<<cnt<<"\n";
    if(g)
        ans /= g,cnt /= g;
    int inv = qmi(cnt, mod - 2, mod)%mod;
    cout<<ans%mod*inv%mod<<"\n";
    return 0;
}