Educational Codeforces Round 100 (Rated for Div. 2) 题解

A. Dungeon

题目
You are playing a new computer game in which you have to fight monsters. In a dungeon you are trying to clear, you met three monsters; the first of them has a health points, the second has b health points, and the third has c.

To kill the monsters, you can use a cannon that, when fired, deals 1 damage to the selected monster. Every 7-th (i. e. shots with numbers 7, 14, 21 etc.) cannon shot is enhanced and deals 1 damage to all monsters, not just one of them. If some monster's current amount of health points is 0, it can't be targeted by a regular shot and does not receive damage from an enhanced shot.

You want to pass the dungeon beautifully, i. e., kill all the monsters with the same enhanced shot (i. e. after some enhanced shot, the health points of each of the monsters should become equal to 0 for the first time). Each shot must hit a monster, i. e. each shot deals damage to at least one monster.

input & output
Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.

Each test case consists of a single line that contains three integers a, b and c (1≤a,b,c≤108) — the number of health points each monster has.

Output
For each test case, print YES if you can kill all the monsters with the same enhanced shot. Otherwise, print NO. You may print each letter in any case (for example, YES, Yes, yes, yEs will all be recognized as positive answer).

Example
inputCopy
3
3 2 4
1 1 1
10 1 7
outputCopy
YES
NO
NO
Note
In the first test case, you can do as follows: 1-th shot to the first monster, 2-th shot to the second monster, 3-th shot to the third monster, 4-th shot to the first monster, 5-th shot to the third monster, 6-th shot to the third monster, and 7-th enhanced shot will kill all the monsters.

In the second test case, you can't kill monsters with the same enhanced shot, because the total number of health points of monsters is 3, and you will kill them in the first 3 shots.

题意
给你三个数 a b c 每秒钟可以选择其中一个使其-1 在第7、14、21 等7的倍数秒的时候a、b、c均-1 问最后能否同时变成0 即 0 0 0

思路
分析可知每次一个周期为7s,每个周期需要改变a、b、c总量为9,为了使最后同时变为0,必须先减少最多的两个,最后不得已在7的倍数秒才减少最少的那个,而要想同时变为0就必须被9整除,因为多一个少一个都不是同时。先判断是否能被9整除,求出之后求出sum/9 即 经过几轮,如果经过的轮数比最小的那个数大,是肯定不行的,剩下的均为可行解。
代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int a,b,c;
		cin>>a>>b>>c;
		int sum = a+b+c;
		if(sum % 9 ==0)
		{
			if(sum/9 > min(a,min(b,c)))
			cout<<"NO\n";
			else
			cout<<"YES\n";
		}
		else
		cout<<"NO\n";
	} 
} 

B. Find The Array

题目
You are given an array [a1,a2,…,an] such that 1≤ai≤109. Let S be the sum of all elements of the array a.

Let's call an array b of n integers beautiful if:

1≤bi≤109 for each i from 1 to n;
for every pair of adjacent integers from the array (bi,bi+1), either bi divides bi+1, or bi+1 divides bi (or both);
2∑i=1n|ai−bi|≤S.
Your task is to find any beautiful array. It can be shown that at least one beautiful array always exists.

input & output
Input
The first line contains one integer t (1≤t≤1000) — the number of test cases.

Each test case consists of two lines. The first line contains one integer n (2≤n≤50).

The second line contains n integers a1,a2,…,an (1≤ai≤109).

Output
For each test case, print the beautiful array b1,b2,…,bn (1≤bi≤109) on a separate line. It can be shown that at least one beautiful array exists under these circumstances. If there are multiple answers, print any of them.

Example
inputCopy
4
5
1 2 3 4 5
2
4 6
2
1 1000000000
6
3 4 8 1 2 3
outputCopy
3 3 3 3 3
3 6
1 1000000000
4 4 8 1 3 3

题意
给你一个数列a 构造一个数列b 满足以下条件
(1)数列有n项
(2)bi+1 是 bi的整数倍或者是bi的因数
(3)两数列对应位置差的绝对值小于第一个数列和的一半,即sum/2

思路
做法1:
统计出a数列中奇数项的和与偶数项的和谁更大,构造b数组的时候把更大的那一项对应位置填上和之前一样的数,这样那一项对应差和就是0,另一个较小的就填1 因为1是任何数的因数 这样就满足条件了。

做法2:
对于a中的每一项取最高位,舍弃其他低位,这样每次的差可以证明都是小于等于ai/2 的 如果每一项都小于等于的话 那么和必然也是

做法3(无法证明的贪心做法)
对于每一项,凑因子,b = b*(a[i]/b) , b = max(1,b) ; 这样取满足了是因子这个条件,但是无法证明为什么满足第三个条件,但是是可以通过的。。

做法1代码

#include <bits/stdc++.h>
using namespace std;
 
const int maxn = 50+10;
 
int a[maxn];
int main()
{
	int t;
	scanf("%d",&t); 
	while(t--)
	{
		int n;
		cin>>n;
		long long even = 0,odd = 0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			if(i&1) odd += a[i];
			else even += a[i];
		}
		if(odd >= even)
		{
			for(int i=1;i<=n;i++)
			if(i&1) printf("%d ",a[i]);
			else printf("%d ",1);
		}
		else
		{
			for(int i=1;i<=n;i++)
			if(i&1) printf("%d ",1);
			else printf("%d ",a[i]);
		}
		puts("");
	}
} 

做法3代码

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100+10;
int a[maxn] ,ans[maxn];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		int b = 1;
		for(int i=1;i<=n;i++)
		{
			b = b * (a[i]/b);
			b = max(b,1);
			ans[i] = b;
		}
		for(int i=1;i<=n;i++) printf("%d ",ans[i]);
		puts("");
	}
}

C. Busy Robot

题目
You have a robot that can move along a number line. At time moment 0 it stands at point 0.

You give n commands to the robot: at time ti seconds you command the robot to go to point xi. Whenever the robot receives a command, it starts moving towards the point xi with the speed of 1 unit per second, and he stops when he reaches that point. However, while the robot is moving, it ignores all the other commands that you give him.

For example, suppose you give three commands to the robot: at time 1 move to point 5, at time 3 move to point 0 and at time 6 move to point 4. Then the robot stands at 0 until time 1, then starts moving towards 5, ignores the second command, reaches 5 at time 6 and immediately starts moving to 4 to execute the third command. At time 7 it reaches 4 and stops there.

You call the command i successful, if there is a time moment in the range [ti,ti+1] (i. e. after you give this command and before you give another one, both bounds inclusive; we consider tn+1=+∞) when the robot is at point xi. Count the number of successful commands. Note that it is possible that an ignored command is successful.

input & output
Input
The first line contains a single integer t (1≤t≤1000) — the number of test cases. The next lines describe the test cases.

The first line of a test case contains a single integer n (1≤n≤105) — the number of commands.

The next n lines describe the commands. The i-th of these lines contains two integers ti and xi (1≤ti≤109, −109≤xi≤109) — the time and the point of the i-th command.

The commands are ordered by time, that is, ti<ti+1 for all possible i.

The sum of n over test cases does not exceed 105.

Output
For each testcase output a single integer — the number of successful commands.

Example
inputCopy
8
3
1 5
3 0
6 4
3
1 5
2 4
10 -5
5
2 -5
3 1
4 1
5 1
6 1
4
3 3
5 -3
9 2
12 0
8
1 1
2 -6
7 2
8 3
12 -9
14 2
18 -1
23 9
5
1 -4
4 -7
6 -1
7 -3
8 -7
2
1 2
2 -2
6
3 10
5 5
8 0
12 -4
14 -7
19 -5
outputCopy
1
2
0
2
1
1
0
2
Note
The movements of the robot in the first test case are described in the problem statement. Only the last command is successful.

In the second test case the second command is successful: the robot passes through target point 4 at time 5. Also, the last command is eventually successful.

In the third test case no command is successful, and the robot stops at −5 at time moment 7.

Here are the 0-indexed sequences of the positions of the robot in each second for each testcase of the example. After the cut all the positions are equal to the last one:

[0,0,1,2,3,4,5,4,4,…]
[0,0,1,2,3,4,5,5,5,5,5,4,3,2,1,0,−1,−2,−3,−4,−5,−5,…]
[0,0,0,−1,−2,−3,−4,−5,−5,…]
[0,0,0,0,1,2,3,3,3,3,2,2,2,1,0,0,…]
[0,0,1,0,−1,−2,−3,−4,−5,−6,−6,−6,−6,−7,−8,−9,−9,−9,−9,−8,−7,−6,−5,−4,−3,−2,−1,−1,…]
[0,0,−1,−2,−3,−4,−4,−3,−2,−1,−1,…]
[0,0,1,2,2,…]
[0,0,0,0,1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1,0,−1,−2,−3,−4,−5,−6,−7,−7,…]

题意
有一个机器人,他可以执行一些指令,每一条指令有开始时间和去往的位置两个参数,如果上一条指令执行完的时间在当前这条指令前面或者相等,便可以执行当前指令,否则当前指令跳过,一直到当前指令开始时间大于等于上一条指令执行结束的时间才能执行当前指令。在固定的时刻到达规定地点便积一分,问最后有几分
t[n+1] 被设定为正无穷

思路
感谢马哥的解惑
分两种情况讨论,一种情况是当前的时间大于等于上一次执行完的时间,这时候需要执行当前指令,修改一下当前的值,每一种情况又有往左走和往右走两种情况,确定区间以后如果当前的x[i] 在区间内,便符合题目要求 答案+1
需要注意的点有
1、在不执行当前指令(仍然在执行之前未执行完指令)的时候,需要“及时停下来” 比如上一条指令只让走到5 但是如果只算t[i+1] - last_time的话 可能会“走过头”
2、有的数据会超过int类型范围 ,比如9999999999 这时候就需要t[n+1]设的尽可能大
代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int maxn = 100000+1000;
 
ll t[maxn] , x[maxn];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%lld%lld",&t[i],&x[i]);
		t[n+1] = INT_MAX ;
		t[n+1] += t[n+1];
		ll pos = 0,ans = 0,now_time = 0,l = 0,r = 0,last_time = 0,last_pos = 0;
		int f = 1; // 1 代表往右走 0 代表往左走 
		for(int i=1;i<=n;i++)
		{
			if(t[i] >= now_time) // 下一条指令来的时候上一条已经结束 
			{
				ll dis = t[i+1] - t[i];
				if(x[i] >= pos)
				{
					f = 1;
					l = pos;
					r = pos + dis;
				}
				else
				{
					f = 0;
					r = pos;
					l = pos - dis;
				}
				if(x[i]>=l && x[i]<=r) ans++;
				last_time = t[i]; // 这次的时间 下个或者接下来好几个要用
				now_time = t[i] + llabs(x[i]-pos); // 现在所在的时刻 (执行完当前指令) 
				last_pos = pos; // 之前的位置 
				pos = x[i]; // 走完的位置 
			}
			else // 
			{
				ll dis1 = t[i] - last_time;
				ll dis2 = min(now_time,t[i+1]) - last_time;
				if(f)
				{
					l = last_pos + dis1;
					r = last_pos + dis2;
				}
				else
				{
					r = last_pos - dis1;
					l = last_pos - dis2;
				}
				if(x[i]>=l && x[i]<=r) ans++;
			}
		}
		cout<<ans<<"\n";
	}
} 
原文地址:https://www.cnblogs.com/liangyj/p/14156758.html