ABC323 A-F

文章介绍了AtCoderUNIQUEVISIONProgrammingContest2023Autumn竞赛中的六个题目,涉及签到、排序、模拟、背包问题、费马小定理和数学思维,展示了不同题目类型的解题方法和思路。
摘要由CSDN通过智能技术生成

目录

A - Weak Beats

tag:签到

题解:

B - Round-Robin Tournament

tag:签到,排序

题解:

C - World Tour Finals

tag:签到,排序

题解:

D - Merge Slimes

tag:模拟

题解:

E - Playlist

tag:背包,费马小定理求逆元

题解:

F - Push and Carry

tag:数学,分类讨论,思维

题解:


比赛传送门

A - Weak Beats

tag:签到

题解:

如果偶数的位置是1就输出No,否则就是Yes。

// 加油昂!!!
// Problem: A - Weak Beats
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Autumn(AtCoder Beginner Contest 323)
// URL: https://atcoder.jp/contests/abc323/tasks/abc323_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"Yes"<<endl;return ;}
#define NO {cout<<"No"<<endl;return ;}
int n, m, k;

void solve()
{
    string s;
    cin >> s;
    for (int i = 0; i < 16; i++)
    {
        if (i % 2 && s[i] == '1') NO 
    }
    YES
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

B - Round-Robin Tournament

tag:签到,排序

题解:

把每个人赢得场次记下来,然后排序即可。

// 加油昂!!!
// Problem: B - Round-Robin Tournament
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Autumn(AtCoder Beginner Contest 323)
// URL: https://atcoder.jp/contests/abc323/tasks/abc323_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 1e5 + 5, M = 1e9 + 7;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
char c[110][110];
void solve()
{
    int n;
    cin >> n;
    map<int,int> mp;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cin >> c[i][j];
            if (i == j) continue;
            if (c[i][j] == 'o')
            {
                mp[i]++;
            }
            else
            {
                mp[j]++;
            }
        }
    }
    vector<pair<int,int>> ans;
    for (int i = 1; i <= n; i++)
    {
        ans.push_back({mp[i], n + 1 - i });
    }
    sort(ans.begin(),ans.end());
    reverse(ans.begin(),ans.end());
    for (auto x:ans) cout <<n + 1 - x.second << " ";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

C - World Tour Finals

tag:签到,排序

题解:

把每个人得到的分数存下来,再把他们没做出来的题目存下来,然后遍历他们每个人,如果没有最大值大,那么就把没做的问题中分数最多的先做了,因此我们还需要对没有做过的题目进行一遍排序,保证我们每次做的题目都是当前没做过的题目中最大的那一个。然后再计数得答案。

// 加油昂!!!
// Problem: C - World Tour Finals
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Autumn(AtCoder Beginner Contest 323)
// URL: https://atcoder.jp/contests/abc323/tasks/abc323_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
typedef double db;
const int N = 1e5 + 5, M = 1e9 + 7;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
vector<int> ans[105];
void solve()
{
    int n, m;
    cin >> n >> m;
    int maxx = 0;
    vector<int> a(m +10), sum(m + 10);
    for (int i = 1; i <= m; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++)
    {
        string s;
        cin >> s;
        s = "?" + s;
        sum[i] = i;
        for (int j = 1; j <= m; j++)
        {
            if (s[j] == 'o') 
            {
                sum[i] += a[j];
            }
            else
            {
                ans[i].push_back(a[j]);
            }
        }
        maxx = max(maxx,sum[i]);
    }
    for (int i = 1; i <= n; i++)
    {
        sort(ans[i].begin(),ans[i].end());
        reverse(ans[i].begin(),ans[i].end());
        int now = 0;
        while (sum[i] < maxx && now < ans[i].size())
        {
            sum[i] += ans[i][now];
            now++;
        }
        cout << now << "\n";
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

D - Merge Slimes

tag:模拟

题解:

本题用一个map实现,从mp.begin()开始,假设当前键是x,如果他的值是大于1的,就将其除2并加到2*x上,一直进行这个操作,如果他的值是奇数,那么原来的值就变为1,统计出1的个数即可。

// 加油昂!!!
// Problem: D - Merge Slimes
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Autumn(AtCoder Beginner Contest 323)
// URL: https://atcoder.jp/contests/abc323/tasks/abc323_d
// Memory Limit: 1024 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;

void solve()
{
    cin >> n;
    map<int,int> mp;
    for (int i = 0; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        mp[x] += y;
    }
    int ans = 0;
    auto now = mp.begin();
    while (now != mp.end())
    {
        int a = 1;
        int x = (*now).first, y = (*now).second;
        if (y > 1) mp[2 * x] += y / 2;
        if (y & 1) ans++;
        now++;
    }
    cout << ans << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

E - Playlist

tag:背包,费马小定理求逆元

题解:

这个题不难看出是一个背包问题的变种,相当于要求的是对于一个背包刚好装满j体积的概率是多少,分析可知,答案肯定是在(x-t[0]+1,x)中,因为他是要求在(x+0.5)的时候正好在播放歌曲1,因此我们直接求出(x-t[0]+1,x)区间的和,然后再乘上(1/n),我们可以首先求出(1/n)的逆元,这样我们后面算出得到的答案就可直接进行计数。

// 加油昂!!!
// Problem: E - Playlist
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Autumn(AtCoder Beginner Contest 323)
// URL: https://atcoder.jp/contests/abc323/tasks/abc323_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, x;
int dp[10005];
int t[1005];
int quick_mi(int a, int b, int p)
{
    int ans = 1 % p;
    while(b)
    {
        if (b & 1) (ans *= a) %= p;
        (a *= a) %= p;
        b >>= 1;
    }
    return ans;
}
void solve()
{
    cin >> n >> x;
    for (int i = 0; i < n; i++)
    {
        cin >> t[i];
    }
    int res = quick_mi(n, mod - 2, mod);
    dp[0] = 1;
    for (int j = 1; j <= x; j++)
    {
        for (int i = 0; i < n; i++)
        {
            if (j < t[i]) continue;
            dp[j] = (dp[j] + dp[j - t[i]] * res) % mod; 
        }
    }
    int ans = 0;
    for (int i = max(0ll, x - t[0] + 1); i <= x; i++)
    {
        ans = (ans + dp[i]) % mod;
    }
    cout << ans * res % mod << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

F - Push and Carry

tag:数学,分类讨论,思维

题解:

(推箱子这个游戏小时候应该都玩过吧)首先,我们想一下,假设我们不需要变换方位,即直接走过去不改变推箱子的方向就能将箱子推到点C,我们需要多少步呢?答案是AB点和BC点的曼哈顿距离之和-1。因为最后点A到的位置是C的旁边一格,所以需要-1,所以只要我们不用特地的改变x的方向,答案就是上面说的这个,那么改变了的该怎么算呢。所以我们这样思考,固定一下点AC的位置,让点C始终在点A的右上方,如果点C在A的下方,沿x轴对称,如果点C在A的左方,沿y轴对称。然后枚举B的位置,分类讨论。每次绕路我们是从正面到了侧面,那么所需的多的步数就是3-1,所以我们每多绕一次路,即要多走2步,最多只会绕两次路。所以我们只需要计算出他变换位置变了几次即可。如下图所示,我们可以分出9个区域(均不包含线段和端点)。我们先考虑这九个区域,假设在1区域上存在一点x,A的路线是先走到点x的左边,将点x推到与C同一直线上,然后再到点的上面去,将该点推到C处,这个过程中,点A共绕路了两次,所以答案是ans+4。有两个特殊的线段是不需要绕路的,即25中间的线段(不包括端点)和56中间的线段(不包括端点),因为这两个方向只需要A在前往C的过程中顺便推一下即可,不会改变A的位置。

其他部分的答案推导同理,可得如下图:

(箭头指向的方向代表该边和哪一个区域的值相等)

注:黑色线的两个非AC点的答案也是ans+2。 

现在就是一个分类讨论,别忘了把点C确定在点A的右上角即可。

// 加油昂!!!
// Problem: F - Push and Carry
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Autumn(AtCoder Beginner Contest 323)
// URL: https://atcoder.jp/contests/abc323/tasks/abc323_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;

void solve()
{
    int xa, ya, xb, yb, xc, yc;
    cin >> xa >> ya >> xb >> yb >> xc >> yc;
    int ans = abs(xa - xb) + abs(ya - yb) + abs(xb - xc) + abs(yb - yc) - 1;
    if (xa > xc)
    {
        xa = -xa;
        xb = -xb;
        xc = -xc;
    }
    if (ya > yc)
    {
        ya = -ya;
        yb = -yb;
        yc = -yc;
    }
    if (xb == xc && yb > ya && yb < yc || yb == yc && xb > xa && xb < xc);
    else if ((xb <= xa && (yb > yc || yb < ya)) || (yb == ya && xb < xa))
    {
        ans += 4;
    }
    else if ((xb > xc && (yb > yc || yb < ya)) || (yb == ya && xb > xc))
    {
        ans += 4;
    }
    else ans += 2;
    cout << ans << "\n";
    
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nov-JovR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值