Panasonic Programming Contest (AtCoder Beginner Contest 195) A~E题解

46 篇文章 7 订阅
43 篇文章 6 订阅

A - Health M Death

题目大意

有一位魔术师,他正在打一个血量为 H H H?的怪兽。
当怪兽的血量是 M M M的倍数时,魔术师能打败怪兽。
魔术师能打败怪兽吗?

1 ≤ M , H ≤ 1000 1\le M,H\le 1000 1M,H1000

输入格式

M   H M~H M H

输出格式

如果魔术师能打败怪兽,输出Yes;如果不能,输出No

样例

M M M H H H输出
10 10 10 120 120 120Yes
10 10 10 125 125 125No

分析

只需判断 H H H是否是 M M M的倍数即可。

代码

#include <cstdio>
using namespace std;

int main()
{
	int m, h;
	scanf("%d%d", &m, &h);
	puts(h % m == 0? "Yes": "No");
	return 0;
}

B - Many Oranges

题目大意

我们有很多橙子。每个橙子的重量在 A A A克到 B B B克之间(包含 A A A B B B克,可能为小数)。
这些橙子的总重量为 W W W千克
找到橙子最少和最多的数量。

1 ≤ A ≤ B ≤ 1000 1\le A\le B\le 1000 1AB1000
1 ≤ W ≤ 1000 1\le W\le 1000 1W1000

输入格式

A   B   W A~B~W A B W

输出格式

输出橙子最少和最多的数量,用一个空格隔开;如果数据不合法,输出UNSATISFIABLE

样例

A A A B B B W W W输出
100 100 100 200 200 200 2 2 2 10   20 10~20 10 20
120 120 120 150 150 150 2 2 2 14   16 14~16 14 16
300 300 300 333 333 333 1 1 1UNSATISFIABLE

分析

如果要得到最小的结果,那么每个橙子的单价必定要取最大值。所以,我们设 m i n = ⌈ W B ⌉ min=\lceil\frac WB\rceil min=BW
同理,如果要得到最大的结果,那么每个橙子的单价必定要取最小值。所以,我们设 m a x = ⌊ W A ⌋ max=\lfloor\frac WA\rfloor max=AW
计算完成后,如果 m i n > m a x min>max min>max,说明数据不合法;否则,输出 m i n min min m a x max max

代码

#include <cstdio>
using namespace std;

int main()
{
	int a, b, w;
	scanf("%d%d%d", &a, &b, &w);
	w *= 1000;
	int min = w % b == 0? w / b: w / b + 1;
	int max = w / a;
	if(min > max) puts("UNSATISFIABLE");
	else printf("%d %d\n", min, max);
	return 0;
}

C - Comma

题目大意

我们写一个整数时,可以从右开始每隔三位写一个逗号。如, 1234567 1234567 1234567写作1,234,567 777 777 777直接写作777
如果我们写下 1 1 1 N N N之间的所有整数,一共要用多少个逗号?

1 ≤ N ≤ 1 0 15 1\le N\le 10^{15} 1N1015

输入格式

N N N

输出格式

输出总共需要的逗号的数量。

样例

N N N输出
1010 1010 1010 11 11 11
27182818284590 27182818284590 27182818284590 107730272137364 107730272137364 107730272137364

分析

我们可以按位置数逗号的数量。首先,在从右往左数的第一个逗号的位置,只要大于 1000 1000 1000的数都需要写逗号。以此类推,在从右往左数的第 N N N个逗号的位置,只要大于 100 0 N 1000^N 1000N的数都需要写逗号。这样,我们就可以通过上述算法写出代码了。

代码

#include <cstdio>
using namespace std;

typedef long long LL;

int main()
{
	LL n, ans = 0LL;
	scanf("%lld", &n);
	for(LL p=1000LL; p<=n; p*=1000LL)
		ans += n - p + 1;
	printf("%lld\n", ans);
	return 0;
}

D - Shipping Center

题目大意

我们有 N N N个包裹(包裹 1 1 1,……,包裹 N N N)和 M M M个盒子(盒子 1 1 1,……,盒子 N N N)。
i i i个包裹的大小和价值分别是 W i W_i Wi V i V_i Vi
i i i个盒子最多只能装一个大小为 X i X_i Xi的包裹。
给你 Q Q Q组询问,每组包含两个整数 L L L R R R,请回答下列问题:

  • 在这 M M M个盒子中,盒子 L , L + 1 , … , R L,L+1,\dots,R L,L+1,,R暂时不可用。请把包裹放进剩余的盒子(不一定要全放)并输出最大可能的总价值。

1 ≤ N , M , Q ≤ 50 1\le N,M,Q\le 50 1N,M,Q50
1 ≤ W i , V i , X i ≤ 1 0 6 1\le W_i,V_i,X_i\le 10^6 1Wi,Vi,Xi106
1 ≤ L ≤ R ≤ M 1\le L\le R\le M 1LRM

输入格式

N   M   Q N~M~Q N M Q
W 1   V 1 W_1~V_1 W1 V1
⋮ \vdots
W N   V N W_N~V_N WN VN
X 1   …   X M X_1~\dots~X_M X1  XM
L 1   R 1 L_1~R_1 L1 R1
⋮ \vdots
L Q   R Q L_Q~R_Q LQ RQ

输出格式

输出 Q Q Q行。第 i i i行应该包含 L i L_i Li R i R_i Ri这个询问对应的答案。

样例

样例输入

3 4 3
1 9
5 3
7 8
1 8 6 9
4 4
1 4
1 3

样例输出

20
0
9

分析

这道题看似很像背包问题,其实不然。我们只需升序排序数组 X X X后,再按顺序贪心地为每个盒子选择它能拿到的价值最高的包裹即可。总时间复杂度为 O ( N M Q ) \mathcal O(NMQ) O(NMQ)

代码

#include <cstdio>
#include <algorithm>
#define maxn 55
using namespace std;

typedef pair<int, int> pii;

pii bags[maxn], boxes[maxn];
bool taken[maxn];

int main()
{
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	for(int i=0; i<n; i++)
		scanf("%d%d", &bags[i].second, &bags[i].first);
	sort(bags, bags + n, greater<pii>());
	for(int i=0; i<m; i++)
		scanf("%d", &boxes[i].first), boxes[i].second = i;
	sort(boxes, boxes + m);
	while(q--)
	{
		int l, r, ans = 0;
		scanf("%d%d", &l, &r);
		l --, r --;
		fill(taken, taken + n, false);
		for(int i=0; i<m; i++)
		{
			auto [size, idx] = boxes[i];
			if(idx < l || idx > r)
			{
				int j = 0;
				for(; j<n; j++)
					if(!taken[j] && bags[j].second <= size)
						break;
				if(j < n)
					ans += bags[j].first, taken[j] = true;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

E - Lucky 7 Battle

题目大意

我们有一个长度为 N N N、由数字0~9组成的字符串 S S S,和一个长度同样为 N N N、由AT组成的字符串 X X X
Takahashi和Aoki要用这两个字符串玩一个 N N N轮的游戏。最开始,他们有一个空的字符串 T T T。在第 i i i轮( 1 ≤ i ≤ N 1\le i\le N 1iN),他们要做下列事情:

  • 如果 X i X_i XiA,Aoki执行下面的操作;如果 X i X_i XiT,则Takahashi执行下面的操作:
  • S i S_i Si或者0加到 T T T的后面。

N N N个操作之后, T T T会变成一个数字0~9组成的字符串。如果我们把它看成一个十进制数(去掉前导 0 0 0),那么如果这个数为 7 7 7的倍数,则Takahashi胜;相反,如果这个数不为 7 7 7的倍数,则Aoki胜。

判断当两个人都按照最优操作进行游戏时,谁会赢。

1 ≤ N ≤ 1 0 5 1\le N\le 10^5 1N105
∣ S ∣ = ∣ X ∣ = N |S|=|X|=N S=X=N

输入格式

N N N
S S S
X X X

输出格式

输出胜者的名字(Takahashi或者Aoki)。

样例

略,请自行前往AtCoder查看

分析

这题首先很容易想到使用搜索。我们定义 w i n n e r ( i , r ) =   \mathrm{winner}(i,r)=~ winner(i,r)= 在第 i i i T   m o d   7 = r T\bmod7=r Tmod7=r最终的赢家。
我们会发现,由于 r r r只有 0 0 0~ 6 6 6,计算重复率较高,所以这题可以使用记忆化搜索来解决。

代码

#include <cstdio>
#include <cstring>
#define AO 0
#define TA 1
#define maxn 200005
using namespace std;

char s[maxn], x[maxn];
int n, dp[maxn][7];

int winner(int i, int r)
{
	if(dp[i][r] != -1) return dp[i][r];
	if(i >= n) return dp[i][r] = r == 0;
	if(winner(i + 1, 10 * r % 7) == TA)
	{
		if(x[i] == 'T')
			return dp[i][r] = TA;
	}
	else if(x[i] == 'A') return dp[i][r] = AO;
	if(winner(i + 1, (10 * r + s[i] - '0') % 7) == TA)
	{
		if(x[i] == 'T')
			return dp[i][r] = TA;
	}
	else if(x[i] == 'A') return dp[i][r] = AO;
	return dp[i][r] = x[i] == 'A';
}

int main()
{
	scanf("%d%s%s", &n, s, x);
	memset(dp, -1, sizeof(dp));
	puts(winner(0, 0) == TA? "Takahashi": "Aoki");
	return 0;
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值