当前位置:   article > 正文

AtCoder Beginner Contest 194 A~E题解_atcoder beginner contest abc194题解

atcoder beginner contest abc194题解

A - I Scream

题目大意

在日本,有如下四种冰淇淋产品:

  • 至少有 15 % 15\% 15%的milk solids和 8 % 8\% 8%的milk fat的产品称为“冰淇淋”;
  • 至少有 10 % 10\% 10%的milk solids和 3 % 3\% 3%的milk fat且不是冰淇淋的产品称为“冰奶”;
  • 至少有 3 % 3\% 3%的milk solids且不是冰淇淋或冰奶**的产品称为“乳冰”;
  • 不是以上三种的产品称为“调味冰”。

在这里,milk solids由milk fat和milk solids-not-fat组成。
有一种冰淇淋产品,它由 A % A\% A%的milk solids-not-fat和 B % B\% B%的milk fat组成。
这种产品是上述的哪一类?

0 ≤ A , B ≤ 100 0\le A,B\le 100 0A,B100
0 ≤ A + B ≤ 100 0\le A+B\le 100 0A+B100

输入格式

A   B A~B A B

输出格式

请按如下格式输出类别:

  • 如果这是冰淇淋,输出 1 1 1
  • 如果这是冰奶,输出 2 2 2
  • 如果这是乳冰,输出 3 3 3
  • 如果这是调味冰,输出 4 4 4

样例

A A A B B B输出
10 10 10 8 8 8 1 1 1
1 1 1 2 2 2 3 3 3
0 0 0 0 0 0 4 4 4

分析

只需将 A A A加上 B B B(变为milk solids的占比),再按题目所说的判断即可。

代码

#include <cstdio>
using namespace std;

int main()
{
	int a, b;
	scanf("%d%d", &a, &b);
	a += b;
	if(a >= 15 && b >= 8) puts("1");
	else if(a >= 10 && b >= 3) puts("2");
	else if(a >= 3) puts("3");
	else puts("4");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

B - Job Assignment

题目大意

你的公司有 N N N位员工,他们叫员工 1 1 1,员工 2 2 2,……,员工 N N N
你有两份重要工作要完成——工作A和工作B。
员工 i i i可以在 A i A_i Ai分钟内完成工作A并在 B i B_i Bi分钟内完成工作B。
你要将两个工作分别分给某一位员工。
假设工作A分给了员工 i i i,工作B分给了员工 j j j,将要花的分钟数设为 t t t,则:
t = { A i + B i ( i = j ) max ⁡ { A i , B j } ( i ≠ j ) t=

{Ai+Bi(i=j)max{Ai,Bj}(ij)
t={Ai+Bimax{Ai,Bj}(i=j)(i=j)
求最小的 t t t

2 ≤ N ≤ 1000 2\le N\le 1000 2N1000
1 ≤ A i , B i ≤ 1 0 5 1\le A_i,B_i\le 10^5 1Ai,Bi105

输入格式

N N N
A 1   B 1 A_1~B_1 A1 B1
A 2   B 2 A_2~B_2 A2 B2
⋮ \vdots
A N   B N A_N~B_N AN BN

输出格式

输出答案。

样例

略,请自行前往AtCoder查看

分析

这题由于 N N N最大只有 1 0 3 10^3 103,所以枚举是完全可行的,只要枚举所有的 ( i , j ) (i,j) (i,j),再根据题目里的公式求出答案取最小值即可,这样做总时间复杂度为 O ( n 2 ) \mathcal O(n^2) O(n2)
另外,本题也有贪心的 O ( n ) \mathcal O(n) O(n)的算法,但是情况太多,代码太麻烦,所以这里不写。

代码

#include <cstdio>
#define maxn 1005
#define INF 2147483647
using namespace std;

int a[maxn], b[maxn];

inline void setmin(int& x, int y) { if(y < x) x = y; }
inline int max(int x, int y) { return x > y ? x : y; }

int main()
{
	int n;
	scanf("%d", &n);
	for(int i=0; i<n; i++)
		scanf("%d%d", a + i, b + i);
	int ans = INF;
	for(int i=0; i<n; i++)
	{
		setmin(ans, a[i] + b[i]); // i == j
		for(int j=i+1; j<n; j++)
		{
			setmin(ans, max(a[i], b[j]));
			setmin(ans, max(a[j], b[i]));
		}
	}
	printf("%d\n", ans);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

C - Squared Error

题目大意

给你一个长度为 N N N的序列 A A A
输出 ∑ i = 2 N ∑ j = 1 i − 1 ( A i − A j ) 2 \displaystyle \sum_{i = 2}^{N} \sum_{j = 1}^{i - 1} (A_i - A_j)^2 i=2Nj=1i1(AiAj)2

2 ≤ N ≤ 3 × 1 0 5 2 \le N \le 3 \times 10^5 2N3×105
∣ A i ∣ ≤ 200 |A_i| \le 200 Ai200

输入格式

N N N
A 1   A 2   A 3   …   A N A_1~A_2~A_3~\dots~A_N A1 A2 A3  AN

输出格式

输出一行,即 ∑ i = 2 N ∑ j = 1 i − 1 ( A i − A j ) 2 \displaystyle \sum_{i = 2}^{N} \sum_{j = 1}^{i - 1} (A_i - A_j)^2 i=2Nj=1i1(AiAj)2

样例

样例输入1

3
2 8 4
  • 1
  • 2

样例输出1

56
  • 1

通过计算,我们得到 ∑ i = 2 N ∑ j = 1 i − 1 ( A i − A j ) 2 = ( 8 − 2 ) 2 + ( 4 − 2 ) 2 + ( 4 − 8 ) 2 = 56 \displaystyle \sum_{i = 2}^{N} \sum_{j = 1}^{i - 1} (A_i - A_j)^2 = (8 - 2)^2 + (4 - 2) ^ 2 + (4 - 8) ^ 2 = 56 i=2Nj=1i1(AiAj)2=(82)2+(42)2+(48)2=56

样例输入2

5
-5 8 9 -4 -3
  • 1
  • 2

样例输出2

950
  • 1

分析

根据公式 ( a − b ) 2 = a 2 + b 2 − 2 a b (a-b)^2=a^2+b^2-2ab (ab)2=a2+b22ab,我们可以使用如下推理:
∑ i = 2 N ∑ j = 1 i − 1 ( A i − A j ) 2 \sum_{i = 2}^{N} \sum_{j = 1}^{i - 1} (A_i - A_j)^2 i=2Nj=1i1(AiAj)2
∑ i = 2 N ∑ j = 1 i − 1 A i 2 + A j 2 − 2 A i A j \sum_{i = 2}^{N} \sum_{j = 1}^{i - 1} {A_i}^2+{A_j}^2-2A_iA_j i=2Nj=1i1Ai2+Aj22AiAj
( ∑ i = 2 N ∑ j = 1 i − 1 A i 2 ) + ( ∑ i = 2 N ∑ j = 1 i − 1 A j 2 ) − ( ∑ i = 2 N ∑ j = 1 i − 1 2 A i A j ) (\sum_{i = 2}^{N} \sum_{j = 1}^{i - 1} {A_i}^2)+(\sum_{i = 2}^{N} \sum_{j = 1}^{i - 1} {A_j}^2)-(\sum_{i = 2}^{N} \sum_{j = 1}^{i - 1} 2A_iA_j) (i=2Nj=1i1Ai2)+(i=2Nj=1i1Aj2)(i=2Nj=1i12AiAj)
这时,我们设 S i = ∑ j = 1 i − 1 A i S_i=\sum\limits_{j=1}^{i-1} A_i Si=j=1i1Ai,则:
( n − 1 ) ( ∑ i = 1 N A i 2 ) − 2 ( ∑ i = 1 N S i A i ) (n-1)(\sum_{i = 1}^{N} {A_i}^2)-2(\sum_{i = 1}^{N} S_iA_i) (n1)(i=1NAi2)2(i=1NSiAi)
这时,计算所有 S i S_i Si的时间复杂度为 O ( n ) \mathcal O(n) O(n),求最终结果的时间复杂度也是 O ( n ) \mathcal O(n) O(n),所以总时间复杂度为 O ( n ) \mathcal O(n) O(n)

代码

#include <cstdio>
#define maxn 300005
using namespace std;

using LL = long long;

int main()
{
	int n, s1 = 0;
	scanf("%d", &n);
	LL s2 = 0, m = 0LL;
	for(int i=0; i<n; i++)
	{
		LL x;
		scanf("%lld", &x);
		m += x * s1;
		s1 += x, s2 += x * x;
	}
	m <<= 1LL, s2 *= n - 1LL;
	printf("%lld\n", s2 - m);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

D - Journey

题目大意

我们有一个 N N N个顶点(称为顶点 1 1 1、顶点 2 2 2、……、顶点 N N N)。
目前,这个图没有任何边。
Takahashi会重复执行以下操作,直到这个图变为连通图:

  • 从这 N N N个顶点中随机选一个顶点。每个顶点被抽中的概率相等,即 1 N \frac 1 N N1
  • 在现在站着的点和选中的顶点之间添加一条边,并走到这个点上。

求Takahashi执行操作次数的期望值。

输入格式

N N N

输出格式

输出答案,最大允许浮点数误差 1 0 − 6 10^{-6} 106

样例

N N N输出
2 2 2 2 2 2
3 3 3 4.5 4.5 4.5

分析

通过dp分析,我们可以得到 ∑ i = 1 n − 1 N i \sum\limits_{i=1}^{n-1}\frac Ni i=1n1iN这个公式。这时,就可以写代码了。

代码

#include <cstdio>
using namespace std;

int main()
{
	int n;
	scanf("%d", &n);
	double res = 0;
	for(int i=1; i<n; i++)
		res += double(n) / i;
	printf("%.8lf\n", res);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

E - Mex Min

题目大意

我们定义 m e x ( x 1 , x 2 , x 3 , … , x k ) \mathrm{mex}(x_1, x_2, x_3, \dots, x_k) mex(x1,x2,x3,,xk)为最小的不出现在 x 1 , x 2 , x 3 , … , x k x_1, x_2, x_3, \dots, x_k x1,x2,x3,,xk中的自然数。
给你一个长度为 N N N的序列 A A A ( A 1 , A 2 , A 3 , … , A N ) (A_1, A_2, A_3, \dots, A_N) (A1,A2,A3,,AN)
对于每个 0 ≤ i ≤ N − M 0\le i\le N-M 0iNM的整数 i i i,我们计算 m e x ( A i + 1 , A i + 2 , A i + 3 , … , A i + M ) \mathrm{mex}(A_{i + 1}, A_{i + 2}, A_{i + 3}, \dots, A_{i + M}) mex(Ai+1,Ai+2,Ai+3,,Ai+M)。输出这些 N − M + 1 N-M+1 NM+1个结果中的最小值。

样例

略,请自行前往AtCoder查看

分析

先用最基本的方法想一下这道题,要求 m e x ( x 1 , x 2 , x 3 , … , x k ) \mathrm{mex}(x_1, x_2, x_3, \dots, x_k) mex(x1,x2,x3,,xk),只需记录每个 x i x_i xi的出现次数,放进数组 cnt \text{cnt} cnt里( cnt i = i \text{cnt}_i=i cnti=i x x x中出现的次数)。这时,只要找到 cnt \text{cnt} cnt中第一个 0 0 0即可,这样计算 m e x \mathrm{mex} mex的时间复杂度为 O ( k ) \mathcal O(k) O(k)。我们还可以想到一种优化方法,就是每一次计算 m e x ( A i + 1 , A i + 2 , A i + 3 , … , A i + M ) \mathrm{mex}(A_{i + 1}, A_{i + 2}, A_{i + 3}, \dots, A_{i + M}) mex(Ai+1,Ai+2,Ai+3,,Ai+M) 1 ≤ i ≤ N − M 1\le i\le N-M 1iNM)时,将 cnt A i \text{cnt}_{A_i} cntAi减少 1 1 1,并且将 cnt A i + M \text{cnt}_{A_{i+M}} cntAi+M增加 1 1 1,这样就达到了 O ( 1 ) \mathcal O(1) O(1)计算 cnt \text{cnt} cnt的效果。但是,即使这样还会TLE。所以,我们可以用一个set维护 cnt \text{cnt} cnt中所有 0 0 0的位置,这样总时间复杂度就能降至 O ( N log ⁡ M ) \mathcal O(N\log M) O(NlogM)

代码

这里注意,set中一定要添加 N N N

#include <cstdio>
#include <set>
#define maxn 1500005
using namespace std;

int cnt[maxn], a[maxn];

set<int> s;

inline void setmin(int& x, int y)
{
	if(y < x) x = y;
}

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i=0; i<n; i++)
		scanf("%d", a + i);
	for(int i=0; i<m; i++)
		cnt[a[i]] ++;
	for(int i=0; i<n; i++)
		if(cnt[i] == 0)
			s.insert(i);
	s.insert(n);
	int ans = *s.begin();
	n -= m;
	for(int i=0; i<n; i++)
	{
		if(cnt[a[i + m]]++ == 0) s.erase(a[i + m]);
		if(--cnt[a[i]] == 0) s.insert(a[i]);
		setmin(ans, *s.begin());
	}
	printf("%d\n", ans);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/74392
推荐阅读
相关标签
  

闽ICP备14008679号