首页 > 其他分享 >AtCoder Beginner Contest 204 A~E 题解

AtCoder Beginner Contest 204 A~E 题解

时间:2024-09-08 21:04:31浏览次数:12  
标签:AtCoder le 204 输出 int 题解 sum 样例 include

A - Rock-paper-scissors

三个人玩石头剪刀布平局,其中两个出的分别是\(x,y\),求另一个人出的。

\(0\le x,y\le 2\)(\(0,1,2\)分别表示石头,剪刀,布)

输入格式

\(x,y\)

输出格式

用整数格式输出答案。

样例

\(x\) \(y\) 输出
\(0\) \(1\) \(2\)
\(0\) \(0\) \(0\)

分析

石头剪刀布这个游戏三人平局只有两种情况(设\(z\)为第三个人出的):

  • \(x=y=z\)
  • \(x\ne y\ne z\)

所以,我们得出如下递推式:
\(z=\begin{cases}x & (x=y)\\3-x-y & (x\ne y)\end{cases}\)

代码

#include <cstdio>
using namespace std;

int main()
{
	int x, y;
	scanf("%d%d", &x, &y);
	printf("%d\n", x == y? x: 3 - x - y);
	return 0;
}

B - Nuts

有\(N\)棵树,第\(i\)棵树上有\(A_i\)颗果实。
一个人会从第\(i\)棵树摘下\(\max(0,A_i-10)\)颗果实。他一共会得到多少果实?

\(1\le N,A_i\le 1000\)

输入格式

\(N\)
\(A_1~\dots~A_N\)

输出格式

输出答案。

样例

样例输入1

3
6 17 28

样例输出1

25

他会从三棵树上分别摘下\(0,7,18\)颗果实,总共\(25\)颗。

样例输入2

4
8 9 10 11

样例输出2

1

他只会从最后一棵树上得到一颗果实。

分析

我们直接按题意模拟即可。

代码

#include <cstdio>
using namespace std;

int main()
{
	int n, ans = 0;
	scanf("%d", &n);
	while(n--)
	{
		int a;
		scanf("%d", &a);
		if(a > 10) ans += a - 10;
	}
	printf("%d\n", ans);
	return 0;
}

C - Tour

一个国家有编号为\(1\)至\(N\)的\(N\)座城市和编号为\(1\)至\(M\)的\(M\)条路。
第\(i\)条路从城市\(A_i\)到\(B_i\),且不能用它从城市\(B_i\)到\(A_i\)。
一个人想从起点城市开始旅行并走过若干条路(可以不走,即只游玩一个城市)并到达终点城市。
有多少种合法的起点和终点城市?如果\(X\ne Y\),则\(X\to Y\)和\(Y\to X\)算作两种不同的方案。

\(2\le N\le 2000\)
\(0\le M\le \min(2000,N(N-1))\)
\(1\le A_i,B_i\le N\)
\(A_i\ne B_i\)
\((A_i,B_i)\)互不相同。

输入格式

\(N~M\)
\(A_1~B_1\)
\(\vdots\)
\(A_M~B_M\)

输出格式

输出答案。

样例

样例输入1

3 3
1 2
2 3
3 2

样例输出1

7

有七种可行的旅游方案:\(1\to1\)、\(1\to2\)、\(1\to3\)、\(2\to2\)、\(2\to3\)、\(3\to2\)、\(3\to3\)。

样例输入2

3 0

样例输出2

3

有三种可行的旅游方案:\(1\to1\)、\(2\to2\)、\(3\to3\)。

分析

我们可以把这个国家看成一个简单有向无权图,并把每个节点作为起点跑一遍\(\text{DFS}\),计算总共能到达的结点数即可。
总时间复杂度为\(\mathcal O(n^2)\)。

代码

注意:每次\(\text{DFS}\)之前一定要将\(\mathrm{vis}\)数组清零!

#include <cstdio>
#include <vector>
#define maxn 2005
using namespace std;

vector<int> G[maxn];
bool vis[maxn];

int ans;

void dfs(int v)
{
	if(vis[v]) return;
	vis[v] = true, ans ++;
	for(int u: G[v])
		dfs(u);
}

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	while(m--)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		G[--x].push_back(--y);
	}
	ans = 0;
	for(int i=0; i<n; i++)
	{
		for(int j=0; j<n; j++)
			vis[j] = false;
		dfs(i);
	}
	printf("%d\n", ans);
	return 0;
}

D - Cooking

两个人要洗\(N\)个碗,其中任意一个人洗第\(i\)个碗需要\(T_i\)分钟。一个人不能同时洗多个碗。
两个人一起洗碗,洗完所有碗至少需要多少分钟?

\(1\le N\le 100\)
\(1\le T_i\le 10^3\)

输入格式

\(N\)
\(T_1~T_2~\dots~T_N\)

输出格式

输出答案。

样例

样例输入1

5
8 3 7 2 5

样例输出1

13

我们可以让两个人分别洗如下的碗:

  • 第一个人洗编号为\(5,1\)的碗。总时间为\(T_5+T_1=13\)分钟。
  • 第二个人洗编号为\(2,4,3\)的碗。总时间为\(T_2+T_4+T_3=10\)分钟。

总耗时为\(\max(13,10)=13\)分钟。

样例输入2

2
1000 1

样例输出2

1000

样例输入3

9
3 14 15 9 26 5 35 89 79

样例输出3

138

分析

这是一道经典01背包题。
题目可以直接描述为:给定序列\(T\),将其分成两个子序列\(A\)和\(B\)(不要求连续),求最小的\(\min(\sum A,\sum B)\)。
这时,我们发现要使\(\min(\sum A,\sum B)\)最小,由于\(\sum A+\sum B=\sum T\),所以\(|\sum A-\sum B|\)必须也达到最小。
我们可以将\(\sum T\)分成两半,其中一半为\(\lfloor\frac{\sum T}2\rfloor\)。这时,我们可以用dp背包解决此题:从\(T\)中选出一个子序列\(A\),使得\(\sum A\le\lfloor\frac{\sum T}2\rfloor\),这样答案就为\(\sum T-\sum A\)。

代码

#include <cstdio>
#define maxn 105
#define maxv 100005
using namespace std;

int dp[maxv], w[maxn];

inline void setmax(int& x, int y)
{
	if(y > x) x = y;
}

int main()
{
	int n, v = 0;
	scanf("%d", &n);
	for(int i=0; i<n; i++)
	{
		scanf("%d", w + i);
		v += w[i];
	}
	int t = v;
	v >>= 1;
	for(int i=0; i<n; i++)
		for(int j=v; j>=w[i]; j--)
			setmax(dp[j], dp[j - w[i]] + w[i]);
	printf("%d\n", t - dp[v]);
	return 0;
}

E - Rush Hour 2

一个国家有\(N\)座城市和\(M\)条路。城市的编号是\(1\)至\(N\),路的编号则为\(1\)至\(M\)。第\(i\)条路双向连接着城市\(A_i\)和\(B_i\)。
在这个国家中,初始时间为\(0\)。如果你在时间点\(t\)通过公路\(i\),所需时间为\(C_i+\lfloor\frac {D_i} {t+1}\rfloor\)。
一个人想从城市\(1\)到达城市\(N\)。他在每个城市可以停留任意自然数的时间。
求这个人最早到达城市\(N\)的时间。如果无法到达城市\(N\),输出-1

\(2\le N\le 10^5\)
\(2\le M\le 10^5\)
\(1\le A_i,B_i\le N\)
\(0\le C_i,D_i\le 10^9\)

输入格式

\(N~M\)
\(A_1~B_1~C_1~D_1\)
\(\vdots\)
\(A_M~B_M~C_M~D_M\)

输出格式

输出答案。

样例

样例输入1

2 1
1 2 2 3

样例输出1

4

我们可以先在城市\(1\)停留至时间\(1\)。然后,我们出发,最终到达时间\(1+2+\lfloor\frac 3 {1+1}\rfloor=4\)。

样例输入2

2 3
1 2 2 3
1 2 2 1
1 1 1 1

样例输出2

3

两个城市之间可能有多条路,一个城市也可能有到自己的路。

样例输入3

4 2
1 2 3 4
3 4 5 6

样例输出3

-1

城市\(1\)到城市\(N\)可能没有路径。

分析

我们可以把输入当成一幅无向图。其实,从一个城市到它自己的路根本没有用,所以我们直接忽略不计。
如果目前时间为\(T\)且我们要从城市\(A_i\)到\(B_i\),我们可以证明,最好的整数出发时间应该是\(\lfloor\sqrt D\rceil-1\)(\(\lfloor x\rceil\)表示\(x\)四舍五入)。
如果\(\lfloor\sqrt D\rceil\le T\),我们应该等到时间\(\lfloor\sqrt D\rceil-1\)再出发;否则,我们直接出发。
这时,我们可以使用Dijkstra最短路算法(使用优先队列优化),这样总时间复杂度就为\(\mathcal O(M\log N)\)。

代码

#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <tuple>
#define maxn 100005
#define INF 9223372036854775807LL
using namespace std;

using Road = tuple<int, int, int>;
using LL = long long;
using pli = pair<LL, int>;

vector<Road> G[maxn];
LL dist[maxn];

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	while(m--)
	{
		int a, b, c, d;
		scanf("%d%d%d%d", &a, &b, &c, &d);
		if(--a == --b) continue;
		G[a].emplace_back(b, c, d);
		G[b].emplace_back(a, c, d);
	}
	dist[0] = 0LL;
	for(int i=1; i<n; i++) dist[i] = INF;
	priority_queue<pli, vector<pli>, greater<pli>> q;
	q.emplace(0LL, 0);
	while(!q.empty())
	{
		auto [t, u] = q.top(); q.pop();
		if(dist[u] != t) continue;
		for(auto [v, c, d]: G[u])
		{
			LL t2 = sqrt((long double) d) - 0.5;
			if(t2 < t) t2 = t;
			t2 += LL(c) + LL(d) / (t2 + 1LL);
			if(t2 < dist[v])
				q.emplace(dist[v] = t2, v);
		}
	}
	if(dist[n - 1] == INF) puts("-1");
	else printf("%lld\n", dist[n - 1]);
	return 0;
}

标签:AtCoder,le,204,输出,int,题解,sum,样例,include
From: https://www.cnblogs.com/stanleys/p/18403472/abc204

相关文章

  • AISing Programming Contest 2021 (AtCoder Beginner Contest 202) A~E 题解
    A-ThreeDice一个人抛了三个骰子,它们的顶面分别是\(a,b,c\)。求它们的底面之和。这里用的骰子是标准骰子,即两个相对的面之和为\(7\)。\(1\lea,b,c\le6\)输入格式\(a~b~c\)输出格式输出答案。样例\(a\)\(b\)\(c\)答案\(1\)\(4\)\(3\)\(13\)\(5\)\(6......
  • AtCoder Beginner Contest 203 (Sponsored by Panasonic) A~E 题解
    A-Chinchirorin题目大意给定三个整数\(a,b,c\),如果它们中有两个相等,输出另一个;否则,输出\(0\)。\(1\lea,b,c\le6\)输入格式\(a~b~c\)输出格式如果\(a,b,c\)中有两个相等,输出另一个;否则,输出\(0\)。样例\(a\)\(b\)\(c\)输出\(2\)\(5\)\(2\)\(5\)\(4\)......
  • AtCoder Beginner Contest 199 (Sponsored by Panasonic) A~E 题解
    A-SquareInequality题目大意给定三个整数\(A,B,C\)。判断\(A^2+B^2<C^2\)是否成立。\(0\leA,B,C\le1000\)输入格式\(A~B~C\)输出格式如果\(A^2+B^2<C^2\),输出Yes;否则,输出No。样例\(A\)\(B\)\(C\)输出\(2\)\(2\)\(4\)Yes\(10\)\(10\)\(10\)N......
  • KYOCERA Programming Contest 2021 (AtCoder Beginner Contest 200) A~E 题解
    A-Century题目大意公元\(N\)年在第几个世纪中?一个世纪是由\(100\)个年份组成的一个区间。如,\(1\)世纪为\([1,100]\)年,\(2\)世纪为\([101,200]\)年,……\(1\leN\le3000\)输入格式\(N\)输出格式将答案输出为一个整数。样例\(N\)输出\(2021\)\(21\)\(200......
  • AtCoder Beginner Contest 205 A~E 题解
    A-kcal题目大意我们有一种每\(100\)毫升含有\(A\)千卡热量的饮料。\(B\)毫升的这种饮料含有多少千卡热量?\(0\leA,B\le1000\)输入格式\(A~B\)输出格式输出\(B\)毫升这种饮料包含的的千卡数。最大允许浮点数精度误差\(10^{-6}\)。样例\(A\)\(B\)输出\(45\)......
  • AtCoder Beginner Contest 168 C~D 题解
    这次比赛的题名很特殊,是由符号+(+英文+)组成的......
  • AtCoder Beginner Contest 171 A~D 题解
    A-αlphabet题目大意输入一个英文字母\(a\),判断它是大写还是小写。输入格式\(a\)输出格式如果\(a\)为小写,输出a;如果\(a\)为大写,输出A。样例输入1B样例输出1AB为大写,所以输出A。样例输入2a样例输出2aa为小写,所以输出a。代码#include<cstdio>usingnames......
  • AtCoder Beginner Contest 187 A~D 题解
    A-LargeDigits题目大意给定两个三位整数\(A\)和\(B\),求它们数位和的最大值。数位和:例如,\(123\)的数位和是\(1+2+3=6\)。\(100\leA,B\le999\)输入格式\(A~~B\)输出格式一行,即\(A\)和\(B\)数位和的最大值。样例输入输出12323495939531710099927......
  • AtCoder Beginner Contest 173 A~D 题解
    A-Payment题目大意如果使用价值\(1000\)元的纸币(假设有)支付\(N\)元,服务员会找多少钱?\(1\leN\le10000\)输入格式\(N\)输出格式一行,即服务员找的钱数。样例输入输出190010030000分析特判:如果\(N\)除以\(1000\)能整除,那么不需要找钱,输出\(0\);如果......
  • Panasonic Programming Contest 2020 C (Sqrt Inequality) 题解
    题目大意输入三个整数\(a\),\(b\),\(c\),如果\(\sqrta+\sqrtb<\sqrtc\)成立,输出Yes,否则输出No。样例输入#1239输出#1No\(\sqrt2+\sqrt3<\sqrt9\)不成立。输入#22310输出#2Yes\(\sqrt2+\sqrt3<\sqrt10\)成立。分析错误思路首先,由......