Codeforces Round #677 (Div. 3)部分题解(除G)

1433A Boring Apartments

题目
There is a building consisting of 10 000 apartments numbered from 1 to 10 000, inclusive.

Call an apartment boring, if its number consists of the same digit. Examples of boring apartments are 11,2,777,9999 and so on.

Our character is a troublemaker, and he calls the intercoms of all boring apartments, till someone answers the call, in the following order:

First he calls all apartments consisting of digit 1, in increasing order (1,11,111,1111).
Next he calls all apartments consisting of digit 2, in increasing order (2,22,222,2222)
And so on.
The resident of the boring apartment x answers the call, and our character stops calling anyone further.

Our character wants to know how many digits he pressed in total and your task is to help him to count the total number of keypresses.

For example, if the resident of boring apartment 22 answered, then our character called apartments with numbers 1,11,111,1111,2,22 and the total number of digits he pressed is 1+2+3+4+1+2=13.

You have to answer t independent test cases.

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

The only line of the test case contains one integer x (1≤x≤9999) — the apartment number of the resident who answered the call. It is guaranteed that x consists of the same digit.

扫描二维码关注公众号,回复: 12091946 查看本文章

Output
For each test case, print the answer: how many digits our character pressed in total.

Example
input
4
22
9999
1
777
output
13
90
1
66

题意
一个按照1,11,111,1111,2,22,222,2222,3……9999这样的序列,问出现到n一共需要写几个数字。

思路
模拟即可

代码

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

#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

const int MAXN = 2e5 + 5;

int t, n, m, k, flag = 1;

int main(void) {
    
    
	IO;
	cin >> t;
	while(t--) {
    
    
		cin >> n;
		int ans = (n % 10 - 1) * 10;
		int now = 1;
		while(n) {
    
    
			n/=10;
			ans += now;
			now++;
		}
		cout << ans << '\n';
	}
}

1433B Yet Another Bookshelf

题目
There is a bookshelf which can fit n books. The i-th position of bookshelf is ai=1 if there is a book on this position and ai=0 otherwise. It is guaranteed that there is at least one book on the bookshelf.

In one move, you can choose some contiguous segment [l;r] consisting of books (i.e. for each i from l to r the condition ai=1 holds) and:

Shift it to the right by 1: move the book at index i to i+1 for all l≤i≤r. This move can be done only if r+1≤n and there is no book at the position r+1.
Shift it to the left by 1: move the book at index i to i−1 for all l≤i≤r. This move can be done only if l−1≥1 and there is no book at the position l−1.
Your task is to find the minimum number of moves required to collect all the books on the shelf as a contiguous (consecutive) segment (i.e. the segment without any gaps).

For example, for a=[0,0,1,0,1] there is a gap between books (a4=0 when a3=1 and a5=1), for a=[1,1,0] there are no gaps between books and for a=[0,0,0] there are also no gaps between books.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤200) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (1≤n≤50) — the number of places on a bookshelf. The second line of the test case contains n integers a1,a2,…,an (0≤ai≤1), where ai is 1 if there is a book at this position and 0 otherwise. It is guaranteed that there is at least one book on the bookshelf.

Output
For each test case, print one integer: the minimum number of moves required to collect all the books on the shelf as a contiguous (consecutive) segment (i.e. the segment without gaps).

Example
input
5
7
0 0 1 0 1 0 1
3
1 0 0
5
1 1 0 0 1
6
1 0 0 0 0 1
5
1 1 0 1 1
output
2
0
2
4
1

题意
一个01序列,每次可以把一段全为1的子串向左或者向右移动一位,问需要多少步把所有1都连在一起。

思路
找最前面的1和最后面的1中间有多少个0就是答案

代码

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

#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

const int MAXN = 2e5 + 5;

int t, n, m, k, flag = 1;
int a[MAXN];
int main(void) {
    
    
	IO;
	cin >> t;
	while(t--) {
    
    
		int l = 0, r = 0, sum = 0;
		cin >> n;
		for(int i = 1; i <= n; i++) {
    
    
			cin >> a[i];
			sum+=a[i];
			if(a[i] && !l)l = i;
			if(a[i])r = i;
		}
		cout << r - l + 1 - sum << '\n';
	}
}

1433C Dominant Piranha

题目
There are n piranhas with sizes a1,a2,…,an in the aquarium. Piranhas are numbered from left to right in order they live in the aquarium.

Scientists of the Berland State University want to find if there is dominant piranha in the aquarium. The piranha is called dominant if it can eat all the other piranhas in the aquarium (except itself, of course). Other piranhas will do nothing while the dominant piranha will eat them.

Because the aquarium is pretty narrow and long, the piranha can eat only one of the adjacent piranhas during one move. Piranha can do as many moves as it needs (or as it can). More precisely:

The piranha i can eat the piranha i−1 if the piranha i−1 exists and ai−1<ai.
The piranha i can eat the piranha i+1 if the piranha i+1 exists and ai+1<ai.
When the piranha i eats some piranha, its size increases by one (ai becomes ai+1).

Your task is to find any dominant piranha in the aquarium or determine if there are no such piranhas.

Note that you have to find any (exactly one) dominant piranha, you don’t have to find all of them.

For example, if a=[5,3,4,4,5], then the third piranha can be dominant. Consider the sequence of its moves:

The piranha eats the second piranha and a becomes [5,5–,4,5] (the underlined piranha is our candidate).
The piranha eats the third piranha and a becomes [5,6–,5].
The piranha eats the first piranha and a becomes [7–,5].
The piranha eats the second piranha and a becomes [8–].
You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (2≤n≤3⋅105) — the number of piranhas in the aquarium. The second line of the test case contains n integers a1,a2,…,an (1≤ai≤109), where ai is the size of the i-th piranha.

It is guaranteed that the sum of n does not exceed 3⋅105 (∑n≤3⋅105).

Output
For each test case, print the answer: -1 if there are no dominant piranhas in the aquarium or index of any dominant piranha otherwise. If there are several answers, you can print any.

Example
input
6
5
5 3 4 4 5
3
1 1 1
5
4 4 3 4 4
5
5 5 4 3 2
3
1 1 2
5
5 4 3 5 5
output
3
-1
4
3
3
1

题意
在一个序列中,一个数字如果大于左或右面的数字,就可以吃掉这个数字并且本身数字+1,问是否有一个数字可以吃掉全部的其他数字

思路
不难理解,只有所有数字全相同时才输出NO,只需要找出序列中最大的数字,并且该数字两边有一个小于它的数字,就是答案。

代码

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

#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

const int MAXN = 3e5 + 5;

int t, n, m, k, flag = 1;
int a[MAXN];
int main(void) {
    
    
	IO;
	cin >> t;
	while(t--) {
    
    
		int ma = 0, ans = 0;
		cin >> n;
		for(int i = 1; i <= n; i++) {
    
    
			cin >> a[i];
			ma = max(a[i], ma);
		}
		a[0] = ma,a[n + 1] = ma;
		for(int i = 1; i <= n; i++) {
    
    
			if(a[i] == ma) {
    
    
				if(a[i + 1] !=ma || a[i - 1] != ma) {
    
    
					ans = i;
					break;
				}
			}
		}
		if(ans)cout << ans << '\n';
		else cout << -1 << '\n';
	}
}

1433D Districts Connection

题目
There are n districts in the town, the i-th district belongs to the ai-th bandit gang. Initially, no districts are connected to each other.

You are the mayor of the city and want to build n−1 two-way roads to connect all districts (two districts can be connected directly or through other connected districts).

If two districts belonging to the same gang are connected directly with a road, this gang will revolt.

You don’t want this so your task is to build n−1 two-way roads in such a way that all districts are reachable from each other (possibly, using intermediate districts) and each pair of directly connected districts belong to different gangs, or determine that it is impossible to build n−1 roads to satisfy all the conditions.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤500) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (2≤n≤5000) — the number of districts. The second line of the test case contains n integers a1,a2,…,an (1≤ai≤109), where ai is the gang the i-th district belongs to.

It is guaranteed that the sum of n does not exceed 5000 (∑n≤5000).

Output
For each test case, print:

NO on the only line if it is impossible to connect all districts satisfying the conditions from the problem statement.
YES on the first line and n−1 roads on the next n−1 lines. Each road should be presented as a pair of integers xi and yi (1≤xi,yi≤n;xi≠yi), where xi and yi are two districts the i-th road connects.
For each road i, the condition a[xi]≠a[yi] should be satisfied. Also, all districts should be reachable from each other (possibly, using intermediate districts).

Example
input
4
5
1 2 2 1 3
3
1 1 1
4
1 1000 101 1000
4
1 2 3 4
output
YES
1 3
3 5
5 4
1 2
NO
YES
1 2
2 3
3 4
YES
1 2
1 3
1 4

题意
有n个城市,每个城市是ai帮派的地盘,现在要修n-1条路,每个连接两个城市,要求每个城市都可以相互到达,但不能将两个相同帮派的城市直接连在一起(为什么相同帮派不能在一起啊???)。

思路
从2到n每个和a1不同帮派的城市都和a1连接起来,然后所有和a1相同的城市和另外一个不同的城市连接起来

代码

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

#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

const int MAXN = 2e5 + 5;

int t, n, m, k;
int a[MAXN];
int ansl[MAXN], ansr[MAXN];
int main(void) {
    
    
	IO;
	cin >> t;
	while(t--) {
    
    
		int flag = 0, num = 0;
		cin >> n;
		for(int i = 1; i <= n; i++) cin >> a[i];
		for(int i = 2; i <= n; i++) {
    
    
			if(a[i] != a[1]) {
    
    
				ansl[++num] = 1;
				ansr[num] = i;
				flag = 1;
			}
		}
		if(!flag) {
    
    
			cout << "NO" << '\n';
			continue;
		}
		for(int i = 2; i <= n; i++) {
    
    
			if(a[i] == a[1]) {
    
    
				ansl[++num] = ansr[1];
				ansr[num] = i;
			}
		}
		cout << "YES" << '\n';
		for(int i = 1; i <= num; i++)
			cout << ansl[i] << ' ' << ansr[i] << '\n';
	}
}

1433E Two Round Dances

题目
One day, n people (n is an even number) met on a plaza and made two round dances, each round dance consists of exactly n/2 people. Your task is to find the number of ways n people can make two round dances if each round dance consists of exactly n/2 people. Each person should belong to exactly one of these two round dances.

Round dance is a dance circle consisting of 1 or more people. Two round dances are indistinguishable (equal) if one can be transformed to another by choosing the first participant. For example, round dances [1,3,4,2], [4,2,1,3] and [2,1,3,4] are indistinguishable.

For example, if n=2 then the number of ways is 1: one round dance consists of the first person and the second one of the second person.

For example, if n=4 then the number of ways is 3. Possible options:

one round dance — [1,2], another — [3,4];
one round dance — [2,4], another — [3,1];
one round dance — [4,1], another — [3,2].
Your task is to find the number of ways n people can make two round dances if each round dance consists of exactly n2 people.

Input
The input contains one integer n (2≤n≤20), n is an even number.

Output
Print one integer — the number of ways to make two round dances. It is guaranteed that the answer fits in the 64-bit integer data type.

Examples
input
2
output
1
input
4
output
3
input
8
output
1260
input
20
output
12164510040883200

题意
把n个人平分成两队,每一队围成一圈,问有多少种排列方式

思路
n个人平分两队就是从n个中选n/2的组合,然后两个环形的排序就是((n-1)!)2种可能性,然后相乘就可以了。

代码

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

#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

const int MAXN = 2e5 + 5;

int t, n, m, k, flag = 1;

int main(void) {
    
    
	IO;
	cin >> n;
	ll ans = 1, x = 1;
	for(ll i = n; i >= n / 2 + 1; i--) ans *= i;
	for(ll i = n / 2; i >= 2; i--) ans /= i;
	for(int i = max(1, n / 2 - 1); i >= 2; i--) x *= i;
	cout << ans / 2 * x * x << '\n';
}

1433F Zero Remainder Sum

题目
You are given a matrix a of size n×m consisting of integers.

You can choose no more than ⌊m/2⌋ elements in each row. Your task is to choose these elements in such a way that their sum is divisible by k and this sum is the maximum.

In other words, you can choose no more than a half (rounded down) of elements in each row, you have to find the maximum sum of these elements divisible by k.

Note that you can choose zero elements (and the sum of such set is 0).

Input
The first line of the input contains three integers n, m and k (1≤n,m,k≤70) — the number of rows in the matrix, the number of columns in the matrix and the value of k. The next n lines contain m elements each, where the j-th element of the i-th row is ai,j (1≤ai,j≤70).

Output
Print one integer — the maximum sum divisible by k you can obtain.

Examples
input
3 4 3
1 2 3 4
5 2 2 2
7 1 1 4
output
24
input
5 5 4
1 2 4 2 1
3 5 1 2 4
1 5 7 1 2
3 8 7 1 2
8 4 7 1 6
output
56

题意
一个n*m的矩阵,每一行最多可以选⌊m/2⌋个数字,问所有选出来的数字和最大是多少,且这个数字和可以整除k。

思路
四维数组DP,dp(i,j,l,r)代表到第i行第j个数字选了l个数字且数字和mod k为r的数字和,用滚动数组优化。
PS.当时没想出来。。看了一位聚聚的博客才明白的。。感觉看了这道题对于dp思维的帮助还是很大的

代码

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

#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

const int MAXN = 2e5 + 5;

int t, n, m, k, flag = 1;
int dp[2][75][40][75];
int a[75][75];
int main(void) {
    
    
	IO;
	cin >> n >> m >> k;
	for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) cin >> a[i][j];
	memset(dp, -1, sizeof(dp));
	dp[0][0][0][0] = 0;
	int now = 0;
	for(int i = 1; i <= n; i++, now ^= 1) {
    
    
		for(int j = 1; j <= m; j++) {
    
    
			for(int l = 0; l <= min(j, m / 2); l++) {
    
    
				for(int r = 0; r < k; r++) {
    
    
					dp[now][j][l][r] = max(dp[now][j][l][r], dp[now][j - 1][l][r]);
					if(l && dp[now][j - 1][l - 1][r] != -1)
						dp[now][j][l][(r + a[i][j]) % k] = max(dp[now][j][l][(r + a[i][j]) % k], dp[now][j - 1][l - 1][r] + a[i][j]);
				}
				for(int r = 0; r < k; r++)
					dp[now ^ 1][0][0][r] = max(dp[now ^ 1][0][0][r], dp[now][j][l][r]);
			}
		}
	}
	cout << dp[now][0][0][0] << '\n';
}

猜你喜欢

转载自blog.csdn.net/qq_45682135/article/details/109277101