ABC323 A-F

什么手速场...拿来水篇题解

ユニークビジョンプログラミングコンテスト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时刻开始播放一首新的歌的概率,状态转移dp[i]=\sum_{j=1}^{n}(i-t[j]>=0?dp[i-t[j]]]*p:0),答案ans=\sum_{i=1}^{x}(i+t[1]>x?p*dp[i]:0)

我自己的代码转移是另一种写法不过思路是一样的

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值