1. 程式人生 > 實用技巧 >Educational Codeforces Round 100 (Rated for Div. 2) 題解

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