什么手速场...拿来水篇题解
ユニークビジョンプログラミングコンテスト2023 秋 (AtCoder Beginner Contest 323) - AtCoder
A - Weak Beats
题意:
给定一个长度为16的01串,问是否01串的每个偶数位上都为0
代码:
#define _CRT_SECURE_NO_WARNINGS
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const LL N = 1e5 + 10, MOD = 998244353, INF = 0x3f3f3f3f;
char ch[20];
void solve()
{
scanf("%s", ch + 1);
for (int i = 2; i <= 16; i += 2)
{
if (ch[i] == '1')
{
printf("No\n");
return;
}
}
printf("Yes\n");
}
int main()
{
int T = 1;
//scanf("%d", &T);
while (T--)
{
solve();
}
return 0;
}
可恶YesNo都大写了吃一发罚时
B - Round-Robin Tournament
题意:
n人pvp。给定一个n*n的图表示每两个人之间打一架的胜负,Si,j为'o'表示人i和人j打一架i赢了。现在给这n个人以第一关键词为胜场数降序,第二关键词为编号升序排序并输出。
题解:
结构体排序
#define _CRT_SECURE_NO_WARNINGS
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const LL N = 1e2 + 10, MOD = 998244353, INF = 0x3f3f3f3f;
PII a[N];
char ch[N];
void solve()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
a[i].second = i;
scanf("%s", ch + 1);
for (int j = 1; j <= n; ++j)
if (ch[j] == 'o')++a[i].first;
}
sort(a + 1, a + 1 + n, [&](PII x, PII y) {
if (x.first != y.first)
return x.first > y.first;
return x.second < y.second;
});
for (int i = 1; i <= n; ++i)
printf("%d ", a[i].second);
}
int main()
{
int T = 1;
//scanf("%d", &T);
while (T--)
{
solve();
}
return 0;
}
C - World Tour Finals
题意:
n人打一场共有m题的竞赛,每题有一个积分ai,给定一个n*m的字符数组,Si,j为'o'表示人i做出了第j题并获得了相应的分数,除了做题得分每个人的得分还需加上他自己的编号i。
问对于每个人最少再做几题能获得第一名。
题解:
先求最大值,然后对于每个人存一个还没做出题的分数的单调队列,优先记高分题即可。
#define _CRT_SECURE_NO_WARNINGS
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const LL N = 1e2 + 10, MOD = 998244353, INF = 0x3f3f3f3f;
int a[N], c[N];
char ch[N][N];
priority_queue<int>q[N];
void solve()
{
int n, m, maxx = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i)
scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i)
{
scanf("%s", ch[i] + 1);
for (int j = 1; j <= m; ++j)
{
if (ch[i][j] == 'o')
c[i] += a[j];
else
q[i].push(a[j]);
}
c[i] += i;
maxx = max(maxx, c[i]);
}
for (int i = 1; i <= n; ++i)
{
int ans = 0;
while (c[i] < maxx)
{
c[i] += q[i].top();
q[i].pop();
++ans;
}
printf("%d\n", ans);
}
}
int main()
{
int T = 1;
//scanf("%d", &T);
while (T--)
{
solve();
}
return 0;
}
D - Merge Slimes
题意:
给出n种史莱姆,第i种史莱姆的大小为si,数量为ci,你可以合并两个大小相等都为X的史莱姆并获得一个大小为2X的史莱姆,该操作可以执行任意次。问进行若干次操作后最少剩多少史莱姆。
题解:
显然能够合成就合成,map瞎搞就行,注意longlong
#define _CRT_SECURE_NO_WARNINGS
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const LL N = 1e5 + 10, MOD = 998244353, INF = 0x3f3f3f3f;
map<LL, LL>mp;
void solve()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
int x, y;
scanf("%d%d", &x, &y);
mp[x] += y;
}
LL ans = 0;
while (mp.size())
{
PLL it = *mp.begin();
mp.erase(mp.begin());
if (it.second > 1)
mp[2 * it.first] += it.second / 2;
ans += it.second % 2;
}
printf("%lld\n", ans);
}
int main()
{
int T = 1;
//scanf("%d", &T);
while (T--)
{
solve();
}
return 0;
}
E - Playlist
题意:
给定一个n首歌的歌单,第i首歌的时长为ti,现在你将对歌单进行随机播放,问第x+0.5时刻播放的是第一首歌的概率是多少(MOD 998244353)。
题解:
数据n<=1e3,x<=1e4,显然可以O(n*x)做。dpi表示在第i时刻开始播放一首新的歌的概率,状态转移,答案
我自己的代码转移是另一种写法不过思路是一样的
#define _CRT_SECURE_NO_WARNINGS
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const LL N = 1e4 + 10, M = 1e3 + 10, MOD = 998244353, INF = 0x3f3f3f3f;
LL dp[N], t[M];
LL qpow(LL x, LL y)
{
x %= MOD;
if (y == 0)return 1;
if (y % 2)
return qpow(x * x, y / 2) * x % MOD;
return qpow(x * x, y / 2) % MOD;
}
void solve()
{
int n, x;
scanf("%d%d", &n, &x);
for (int i = 1; i <= n; ++i)
scanf("%lld", &t[i]);
LL p = qpow(n, MOD - 2), ans = 0;
dp[0] = 1;
for (int i = 0; i <= x; ++i)
{
if (i + t[1] > x)
ans = (ans + dp[i] * p) % MOD;
for (int j = 1; j <= n; ++j)
{
if (i + t[j] <= x)
dp[i + t[j]] = (dp[i + t[j]] + dp[i] * p) % MOD;
}
}
printf("%lld\n", ans);
}
int main()
{
int T = 1;
//scanf("%d", &T);
while (T--)
{
solve();
}
return 0;
}
F - Push and Carry
题意:
推箱子,任务初始在xa,ya,箱子初始在xb,yb,你需要把箱子退到xc.yc,问最少需要多少步
题解:
sb模拟题,枚举所有方向,在枚举先推哪个面取min即可(不一定只有这种做法,只是我觉得这样做简单)
#define _CRT_SECURE_NO_WARNINGS
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const LL N = 1e4 + 10, M = 1e3 + 10, MOD = 998244353, INF = 0x3f3f3f3f;
void solve()
{
LL xa, ya, xb, yb, xc, yc, ans = 1e18;
scanf("%lld%lld%lld%lld%lld%lld", &xa, &ya, &xb, &yb, &xc, &yc);
if (xb <= xc)//上.平
{
if (yb <= yc)//左上.左.上
{
LL res = 0;
res += abs(xb - 1 - xa) + abs(yb - ya);//先去上.下推.对齐x
if (ya == yb && xa > xb)res += 2;//绕道
res += xc - xb;
if (yb == yc)ans = min(ans, res);
res += 2 + yc - yb;
ans = min(ans, res);
res = 0;
res += abs(xb - xa) + abs(yb - 1 - ya);
if (xa == xb && ya > yb)res += 2;
res += yc - yb;
if (xb == xc)ans = min(ans, res);
res += 2 + xc - xb;
ans = min(ans, res);
}
else//右上.右
{
LL res = 0;
res += abs(xb - 1 - xa) + abs(yb - ya);//先对齐x
if (ya == yb && xa > xb)res += 2;//绕道
res += xc - xb;
res += 2 + yb - yc;
ans = min(ans, res);
res = 0;
res += abs(xb - xa) + abs(yb + 1 - ya);
if (xa == xb && ya < yb)res += 2;
res += yb - yc;
if (xb == xc)ans = min(ans, res);
res += 2 + xc - xb;
ans = min(ans, res);
}
}
else//下
{
if (yb <= yc)//左下.下
{
LL res = 0;
res += abs(xb + 1 - xa) + abs(yb - ya);//先去对齐x
if (ya == yb && xa < xb)res += 2;//绕道
res += xb - xc;
if (yb == yc)ans = min(ans, res);
res += 2 + yc - yb;
ans = min(ans, res);
res = 0;
res += abs(xb - xa) + abs(yb - 1 - ya);
if (xa == xb && ya > yb)res += 2;
res += yc - yb;
res += 2 + xb - xc;
ans = min(ans, res);
}
else//右下
{
LL res = 0;
res += abs(xb + 1 - xa) + abs(yb - ya);//先对齐x
if (ya == yb && xa < xb)res += 2;//绕道
res += xb - xc;
res += 2 + yb - yc;
ans = min(ans, res);
res = 0;
res += abs(xb - xa) + abs(yb + 1 - ya);
if (xa == xb && ya < yb)res += 2;
res += yb - yc;
res += 2 + xb - xc;
ans = min(ans, res);
}
}
printf("%lld\n", ans);
}
int main()
{
int T = 1;
//scanf("%d", &T);
while (T--)
{
solve();
}
return 0;
}