Algorithm written test questions

Meituan Xiaomei sorting

The arrangement of n means that there is an array [pi] with a length of n. All the numbers in it are different and are between 1 and n. For example, [3, 1, 2] is an arrangement of 3. Xiaomei wants to arrange the sequence into an increasing sequence, that is, [1, 2, 3, …, n], but she can only perform one operation. First, she has to randomly select two different numbers from the arrangement. Then she placed the larger of the two numbers at the end of the array and the smaller one at the first. She can do this an unlimited number of times. Ask her how many times it takes at least to arrange the sorting into an ascending sequence.

Question analysis : Every time you take two, you must put them at both ends. Then the largest and smallest cannot be taken out at the first time, otherwise they will be wrapped in it. Therefore, this question belongs to a greedy algorithm. First, look at the order of the two middle ones. (For example, the subscript of the number 3 must be before the subscript of 4). If it is satisfied, then look at the ones on both sides of them. If it is not satisfied, then the middle one must be taken out first and placed on both sides, and the rest must be taken out. The number of times is n/2.

Sample input

5
1 5 4 2 3

Sample output

2
#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

void main() {
	int n;
	cin >> n;
	vector<int> nums(n);
	for (int i = 0; i < n; i++) {
		cin >> nums[i];
	}
	unordered_map<int, int> mp;
	for (int i = 0; i < n; i++) {
		mp[nums[i]] = i;
	}
	int i, j;
	if (n % 2){
		i = n / 2;
		j = n / 2 + 2;
	}
	else {
		i = n / 2;
		j = n / 2 + 1;
	}
	int result = n / 2;
	while (i >= 0) {
		if (mp[i] < mp[j]) result--;
		if (mp[i - 1] < mp[i] && mp[j] < mp[j + 1]) {
			i--;
			j++;
		}
		else break;
	}
	cout << result << endl;
}

Meituan Xiaomei’s tree

Xiaomei has a tree in the forest. Trees grow every year, and the growth is random but also regular.

1. Each node will grow at most one child node every year (it may not grow long)

2. The new node that year must be a leaf node.

3. The root of the tree is 1

Given two trees, please judge whether the first tree is likely to grow into the second tree next year.

Enter description

First enter T to represent T group of data

For each set of data, it contains 4 rows,

The first line is the number of nodes of the first tree: n.

The second line has n-1 numbers li (i=2,3,...,n), indicating that the father of the i-th node is li.

The third line is the number of nodes of the second tree: m.

The fourth line has m-1 numbers ri (i=2,3,...,n) indicating that the father of the i-th node is ri.

The input ensures that the corresponding node numbers of the two trees are the same, that is, the common point parent nodes of the two trees are the same, and the second tree includes all nodes of the first tree.

1≤n,m≤50000, 1≤li,ri≤i, 1≤T≤10

Output description

If the first tree is likely to grow into the second tree next year, output "yes", otherwise output "no".

1
4
1 1 2
6
1 1 2 2 4

Sample output

yes

hint

输入样例2
1
4
1 1 2
6
1 1 2 4 5
输出样例2
no样例解释2
样例2中5为新生节点,不应有子节点。

输入样例3
2
4
1 1 2
6
1 1 2 2 4
4
1 1 2
6
1 1 2 4 5
输出样例3
yes
no

Problem analysis : Restrictions 1. Each existing node can only generate at most one node, which means that the part after tree_2 cannot have repeated numbers, otherwise it will grow out of a parent node. Restriction 2: The new node in the current year must be a leaf node, which means that the new node in the current year can only grow from the first tree, and cannot grow from the new node. That is, the part after tree_2 cannot be greater than the summary point value of tree_1. number.

#include <iostream>
#include <vector>

using namespace std;
int main() {
	int T;
	cin >> T;
	vector<int> ns(T);
	vector<vector<int>> nnum(T);
	vector<int> ms(T);
	vector<vector<int>> mnum(T);
	for (int i = 0; i < T; i++) {
		cin >> ns[i];
		for (int j = 0; j < (ns[i] - 1); j++) {
			int n;
			cin >> n;
			nnum[i].push_back(n);
		}
		cin >> ms[i];
		for (int j = 0; j < (ms[i] - 1); j++) {
			int m;
			cin >> m;
			mnum[i].push_back(m);
		}
	}
	for (int i = 0; i < T; i++) {
		int n = ns[i];
		int m = ms[i];
		vector<int> tree_1 = nnum[i];
		vector<int> tree_2 = mnum[i];
		bool istrue = false;
		for (int j = tree_1.size(); j < tree_2.size(); j++) {
			if (tree_2[j] > n) {
				cout << "no" << endl;
				istrue = true;
				break;
			}
			if (j > tree_1.size() && tree_2[j] == tree_2[j - 1]) {
				cout << "no" << endl;
				istrue = true;
				break;
			}
		}
		if (!istrue) cout << "yes" << endl;
	}
	return 0;
}

Meituan Xiaomei’s folder

Xiaomei likes to organize computer file paths. But she didn't like going through the folders one by one. So she wrote a program that wrote the file information into a line of HTML-like code. Among them, "<folder:name1 >...<\folder>" represents a folder called name1. The ellipses may include folders and files. "<file:name2\ >" represents a file called name2. There are only these two kinds of information in the code, and the file name or folder name is guaranteed not to include ">", "<" or "\" and is not empty. Folder names in the same folder are different, and the file name Each is different. Xiaomei wants to clear useless folders in the folder, that is, empty folders. The specific definition is: (1) A folder without any files and folders is an empty folder (2) A folder that only contains empty folders is also an empty folder. That is, a folder without any files in the current directory tree is an empty folder. Xiaomei wants to know how many empty folders there are.

Enter description

The question includes T group data

For each set of data, it contains 1 row of string s.

1≤|s|≤50000, 1≤T≤5

Output description

For each set of data, output an integer representing the number of empty folders.

Sample input

2
<folder:name1><folder:name2><folder:name3><\folder><\folder><file:name4\><\folder>
<folder:name1><folder:name2><folder:name3><file:name4\><\folder><\folder><\folder>

Sample output

2
0

 Question analysis: Each folder ends with <\folder>, and the things at the beginning and between them belong to the folder. It is similar to the feeling of Xiaoxiaole. Every time you get a <\folder>, you Take the beginning of a folder in front of it and form a pair with it. This is the problem of the stack. When the beginning of the folder is encountered, it is pushed into the stack first. When the file <file:name2\> is encountered, it means that the file is between the beginning and the end of the folder. The folders in the stack are not empty and are returned directly. . When the end of the folder is reached before the file is encountered, it means that there is no file in the folder, and we directly res++ the empty file. Another thing to note about this question is that when calling getline after cin, you must first cin.ignore(). There is also the problem of string escaping. In order to prevent escaping, we add an extra \ to indicate that the following \ is not escaped.

#include <iostream>
#include <vector>
#include <string>
#include <stack>

using namespace std;

int main() {
	int T;
	cin >> T;
	cin.ignore(); //这一行很关键,不然下面的getline会读取到上面的cin最后的回车符。
	vector<int> result(T, 0);
	for (int i = 0; i < T; i++) {
		string s;
		stack<string> folders;
		getline(cin, s);
		int start = 0;
		int res = 0;
		for (int j = 0; j < s.size(); j++) {
			if (s[j] == '>') {
				string fold = s.substr(start, j - start + 1);
				start = j + 1;
				if (fold != "<\\folder>") {  //这里两个斜杠是为了防止转义
					folders.push(fold);
				}
				else {
					string file = folders.top();
					folders.pop();
					string head = file.substr(0, 5);
					if (head == "<file") {
						result[i] = res;
						break;
					}
					else {
						res++;
					}
				}
			}
		}
	}
	for (int i = 0; i < T; i++) {
		cout << result[i] << endl;
	}
	return 0;
}

Huawei batch initialization times

A certain department is developing a code analysis tool that needs to analyze the dependencies between modules to determine the initialization sequence of the modules, whether there are loop dependencies, etc. "Batch initialization" means that one or more modules can be initialized at a time. For example, module 1 depends on module 2, and module 3 also depends on module 2, but modules 1 and 3 have no dependency. Then module 2 must be "batch initialized" first, and then modules 1 and 3 must be "batch initialized". Now given a set of dependencies between modules, please calculate the number of times "batch initialization" is required.

answer requests

Time limit : C/C++ 1000ms. Other languages: 2000ms

Memory limit : C/C++ 256MB, other languages: 512MB

enter

(1) Line 1 has only one number, indicating the total number of modules N.

(2) The subsequent N lines represent the dependency data of modules 1 to N in sequence. The first number in each line represents the number of dependent modules (not exceeding N), and the subsequent numbers represent the ID sequence that the current module depends on. The same number will not appear repeatedly in this sequence, and the value of the module ID is set within [1, N].

(3) The value range of the total number of modules N is 1<=N<=1000.

(4) The numbers in each line are separated by 1 space.

output

Output "number of batch initializations". If there are cyclic dependencies that cannot be initialized, output -1.

Sample 1

    输入: 5
          3 2 3 4
          1 5
          1 5
          0
    输出: 3
解释:共5个模块。
模块1依赖模块2、3、4;
模块2依赖模块5
模块3依赖模块5
模块4依赖模块5
模块5没有依赖任何模块
批量初始化顺序为{5}->{2,3,4}->{1},共需”批量初始化”3次

Sample 2

    输入: 3
          1 2
          1 3
          1 1  
    输出: -1
解释:存在循环依赖,无法完成初始化,返回-1
#include <string>
#include <iostream>
#include <vector>
#include <stack>
#include <unordered_map>
using namespace std;

int resetnum = -1;

void dfs(vector<vector<int>>& neednodes, vector<bool>& visiter, int result) {
	int have_vis = 0;
	for (int i = 0; i < visiter.size(); i++) {
		if (visiter[i]) have_vis++;
	}
	if (have_vis == visiter.size()) {
		resetnum = result;
		return;
	}
	bool no_change = true;
	for (int i = 0; i < visiter.size(); i++) {
		if (visiter[i]) continue;
		vector<int> need = neednodes[i];
		bool all_need = true;
		for (int j = 0; j < need.size(); j++) {
			if (visiter[need[j] - 1]) continue;
			else {
				all_need = false;
				break;
			}
		}
		if (!all_need) continue;
		else {
			visiter[i] = true;
			no_change = false;
		}
	}
	if (no_change) return;
	dfs(neednodes, visiter, result + 1);
}

int main() {
	int N;
	cin >> N;
	vector<vector<int>> neednodes;
	for (int i = 0; i < N; i++) {
		int num;
		cin >> num;
		vector<int> neednode(num);
		for (int j = 0; j < num; j++) {
			cin >> neednode[j];
		}
		neednodes.push_back(neednode);
	}
	vector<bool> visiter(N, false);
	dfs(neednodes, visiter, 0);
	cout << resetnum << endl;
}

Huawei

#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <unordered_map>
using namespace std;

int main() {
	int start;
	int end;
	cin >> start >> end;
	vector<int> ID;
	unordered_map<int, bool> visited;
	for (int i = start; i <= end; i++) {
		ID.push_back(i);
		visited[i] = false;
	}
	int n;
	cin >> n;
	vector<pair<int, int>> works(n);
	for (int i = 0; i < n; i++) {
		cin >> works[i].first >> works[i].second;
	}
	for (int i = 0; i < n; i++) {
		if (works[i].first == 1 && works[i].second <= ID.size()) {
			int num = works[i].second;
			while (num--) {
				visited[ID[0]] = true;
				ID.erase(ID.begin());
			}
		}
		else if (works[i].first == 2) {
			if (visited[works[i].second]) continue;
			if (works[i].second < start || works[i].second > end) continue;
			int j = 0;
			while (ID[j] != works[i].second) j++;
			ID.erase(ID.begin() + j);
			visited[works[i].second] = true;
		}
		else {
			if (works[i].second < start || works[i].second > end) continue;
			if (!visited[works[i].second]) continue;
			visited[works[i].second] = false;
			ID.push_back(works[i].second);
		}
	}
	cout << ID[0] << endl;
}

UFIDA calculates the area divided by straight lines

 In the Cartesian coordinate system, there is an area [A, B], which is divided into multiple small areas by different lines. For simplicity, it is assumed that these different lines are all straight lines and there is no situation where three straight lines intersect at one point.

So, how to quickly calculate how many blocks the area of ​​[A, B] on the X coordinate axis is divided by straight lines at a certain moment?

The A-axis is parallel to the Y-axis, A (x=1)

The B axis is parallel to the Y axis, B(x = 20);

Enter description

The input adopts multi-line input, with 4 data in one line, representing two coordinate points respectively, and one line in one line;

1, 4, 20,100 - represents two points, the coordinates of point t1 are (1,4), and the coordinates of point t2 are (20,100)

Output description

The output is an integer, indicating the number of areas divided by the input line segments.

Example 1

enter

1,37,20,4
1,7,20,121

output

4

Remark

AB之间的线段不平行于Y轴

 Question analysis: There are two difficulties in this question, one is input. If the number is not given, multiple lines must be entered at one time and must be received using while. Another technique is to add a line to the area number by adding 1 for each intersection with other lines.

#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
using namespace std;

int main() {
	int x1, y1, x2, y2;
	int result = 1;
	vector<vector<int>> lines;
	while (cin >> x1 >> y1 >> x2 >> y2) {
		result++;
		for (auto& line : lines) {
			if ((line[1] > y1 && line[3] > y2) || (line[1] < y1 && line[3] < y2) || line[1] == y1 || line[3] == y2) {
				continue;
			}
			result++;
		}
		lines.push_back({ x1, y1, x2, y2 });
	}
	cout << result << endl;
	return 0;
}

UF’s best interview strategies

Xiao Ming is looking for a job recently and has received many interview invitations. The interviews that can be attended are represented by the interviews array, where interviews[i] = [startTimei, endTimei, possibilityi], indicating that the i-th interview starts at startTimei and ends at endTimei. The interview is successful. The possibility is possibilityi. The larger the value, the greater the possibility of passing the interview. Due to energy limitations, Xiao Ming can participate in up to k interviews.

Xiao Ming can only participate in one interview at the same time. If he wants to participate in a certain interview, he must participate in the entire interview to pass the interview. That is, he cannot participate in two interviews with the same start time and the same end time at the same time.

Please give the maximum sum of Xiao Ming’s chances of succeeding in the interview.

Example 1

enter

[[1,2,3],[3,4,2],[2,4,4]],2

output

5

illustrate

小明参加 [1, 2, 3], [3, 4, 2] 两场面试,面试通过可能性的和为 3 + 2 = 5

Example 2

enter

[[1,2,3],[3,4,2],[2,4,6]],2

output

6

illustrate

只参加面试 [2, 4, 6],面试通过的可能性的和最大,为 6 

Question analysis : It is a bit like the question about merging intervals in hot100, but this question can only be answered by K questions at most, and the result must be the highest. At first I thought of DP, dynamic programming, but I couldn't figure out what dp[i][j] represented. So the backtracking brute force solution is used. Every time you reach a node, you have two options, one is to interview, the other is not to interview. At the same time, the interview is also conditional, that is, the starting time of the current node must be greater than the current deadline of no time. Then the termination condition of the backtracking is that the number of interviews reaches K for the first time, and the interview traversal for the second time is completed. So our backtracking parameters include the following table index of the currently traversed node, and the count of the current interviews. 

#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
using namespace std;

int result = 0;
void dfs(vector<vector<int>>& interviews, int index, int count, int k, int end_length, int res) {
	if (count == k) {
		result = max(result, res);
		return;
	}
	if (index >= interviews.size()) {
		result = max(result, res);
		return;
	}
	if (interviews[index][0] > end_length) {
		dfs(interviews, index + 1, count + 1, k, interviews[index][1], res + interviews[index][2]);
	}
	dfs(interviews, index + 1, count, k, end_length, res);
}
int main() {
	vector<vector<int>> interviews = { {1, 2, 3}, {3, 4, 2} ,{2, 4, 6} };
	int k = 2;
	sort(interviews.begin(), interviews.end(), [](const vector<int>& a1, const vector<int>& a2) {
		if (a1[0] == a2[0]) return a1[1] < a2[1];
		return a1[0] < a2[0];
		});
	dfs(interviews, 0, 0, k, 0, 0);
	cout << result << endl;
	return 0;
}

The shortest path between UFIDA planets

In a distant galaxy, there are N planets (numbered from 1 to N), and these planets are connected through star gates. Each stargate connects two planets and allows travel in both directions.

The opening of each stargate requires a certain amount of energy, which is represented by the number on the stargate. The numbers on each stargate are unique.

Now, for some reason, all the stargates are closed. As an explorer, your task is to find a way to open the fewest stargates so that all planets are connected to other planets through at least one open stargate.

Give you some connectable options connections, where connections[i] = [Xi, Yi, Mi] means that an interstellar gate can be opened between planet Xi and planet Yi and consume Mi energy.

Calculate the minimum energy consumption required to connect all planets. If all planets cannot be connected, output -1.

Example 1

enter

3,[[1, 2, 5], [1, 3, 6], [2, 3, 1]]

output

6

Remark

1 ≤ N ≤ 100

 Question analysis: This question is a typical minimum spanning tree problem. The question is a graph with weights. Your task is to use the minimum cost to connect all the points in the graph together. The weights used to connect them are The minimum value. The question requires connecting all the planets, which is equivalent to constructing a graph. At the same time, the edge weight needs to be minimum.

There are generally two solutions to the minimum spanning tree: Prim's method and Kruskal's algorithm. Today I mainly work on prim algorithm.

Divide the points in the tree into two categories, category A has been traversed, and category B has not been traversed. They are all in class B at the beginning. Randomly select one from B to join class A, then look at the point in class B with the smallest weight from the node of class A, add it to A, and then find the point from B closest to A, all the time. There are no vertices in B.

First build the adjacency list, traverse the known paths, and then put the connection relationship and weight into the adjacency list. Visited is constructed to prevent multiple traversals of a node, and dist indicates that the minimum distance from the point in B (traversed) to this point is initialized to infinity. Every time we find the closest point, we use a small top heap to implement it and call the priority queue. The pair inside saves the minimum cost to reach this point and the subscript of this point.

First initialize the first point to 0, which means adding it to A, its dist will become 0, and putting it into the priority queue. while(que)

Take out one, if visited, continue, traverse its adjacent nodes if they have not been encountered. If the adjacent nodes have not been traversed, and the weight of the adjacent node reached at the same time is less than dist[nearby], then this adjacent node and its minimum Connection weights are put in.

#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
#include <queue>
using namespace std;


int prim(vector<vector<int>>& connections, int N) {
	int result = 0;
	vector<vector<pair<int, int>>> graph(N + 1);
	for (auto& con : connections) {
		graph[con[0]].push_back({ con[1], con[2] });
		graph[con[1]].push_back({ con[0], con[2] });
	}
	vector<bool> visit(N + 1, false);
	vector<int> dist(N + 1, INT_MAX);
	dist[1] = 0;
	priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> que;
	que.push({ 0, 1 });
	while (!que.empty()) {
		int weight = que.top().first;
		int node = que.top().second;
		que.pop();
		if (visit[node]) continue;
		visit[node] = true;
		result += weight;
		for (auto neighbor : graph[node]) {
			int neighbornode = neighbor.first;
			int weigh = neighbor.second;
			if (!visit[neighbornode] && weigh < dist[neighbornode]) {
				dist[neighbornode] = weigh;
				que.push({ weigh, neighbornode });
			}
		}
	}
	for (int i = 1; i <= N; i++) {
		if (!visit[i]) return  -1;
	}
	return result;
}

int main() {
	vector<vector<int>> connections = { {1, 2, 5}, {1, 3, 6}, {2, 3, 1} };
	int N = 3;
	int result = prim(connections, N);
	cout << result << endl;
	return 0;
}

Meituan Xiaomei’s tree dyeing (the final question of the 2023 autumn recruitment)

Xiaomei got a tree, and each node has a weight. Initially each node is white.

Xiaomei has several operations, and each operation can select two adjacent nodes. If they are both white and the product of the weights is a perfect square number, Xiaomei can dye these two nodes red at the same time.

Xiaomei wants to know, how many nodes can she dye red at most?

Enter description

The first line enters a positive integer n, representing the number of nodes. The second line inputs n positive integers ai, representing the weight of each node. In the next n-1 lines, each line inputs two positive integers u and v, which means that node u and node v are connected by an edge.

picture

Output description

Output an integer indicating the maximum number of nodes that can be dyed red.

Example 1

enter

3
3 3 12
1 2
2 3

output

2

illustrate

可以染红第二个和第三个节点。

请注意,此时不能再染红第一个和第二个节点,因为第二个节点已经被染红。

因此,最多染红 2 个节点。

Question analysis: This question is about a tree structure. Each time two adjacent ones that meet the conditions are dyed, then if a parent node is dyed with one of its child nodes, it cannot be dyed with other child nodes. This is A very important recursive logic. This question is a typical tree DP algorithm. There are two states for a node, one is that it is not dyed, and the other is that it is dyed.

Each time DFS is passed, the current node and its parent node are passed in to prevent it from going backwards from the current node to the parent node. In other words, it can only be done from top to bottom. At the same time, whether the parent node is dyed or not depends on the status of the child node, so we first recurse to the bottom node, and then dp up step by step.

#include <iostream>
#include <vector>
using namespace std;

void dfs(int u, int fa, vector<vector<int>>& g, vector<int>& a, vector<vector<int>>& dp) {
	for (int v : g[u]) {
		if (v == fa) continue;
		dfs(v, u, g, a, dp);
		dp[u][0] += max(dp[v][0], dp[v][1]); //这里每次子节点dfs处理完,都会取子节点的max,然后更新u的不染红的情况。
		//这里u不染色时,他的子节点既可以染色(子节点a和a的子节点染色),也可以不染色。所以取max
	}
	for (int v : g[u]) {
		if (v == fa) continue;
		long long val = a[v] * a[u]; //要是想把uv都染色,就要看uv满不满足条件
		long long sq = sqrt(val);
		if (sq * sq != val) continue;
		dp[u][1] = max(dp[u][1], dp[u][0] - max(dp[v][0], dp[v][1]) + dp[v][0] + 2);
		//这里如果u想染色,前面必须满足条件,然后因为是for循环,我们要看u和哪个子节点一起染色时值最大。所以在循环里不断取max
		//这里的dp[u][1]表示u和当前v染色的情况,那么这个uv都必须空出来,这样才能染色。所以我们一开始就要找u不染色的节点数dp[u][0],但是dp[u][0]里包含了v的染色和不染色的情况(看第九行),所以我们减去这个值也就是max(dp[v][0],dp[v][1]),
		//此时dp[u][0] - max(dp[v][0], dp[v][1])表示的是不染色u节点,同时不考虑v分支时的染色个数,那么我们想染色v,就必须把v空出来,所以加dp[v][0]表示不染色v时v下面的分支有多少,最后再加2,表示uv这两个节点染色。
	}
}

int main() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	vector<vector<int>> g(n);
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		--u, --v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector<vector<int>> dp(n, vector<int>(2, 0));
	dfs(0, -1, g, a, dp);
	cout << max(dp[0][0], dp[0][1]);
	return 0;
}

Soul draw card

The known probability of the card drawing system in "Genshin Impact" and "Honkai: Star Rail" is as follows:

When the big guarantee mechanism is not triggered, each draw has a p/2 probability of drawing 5 stars in the current period, a p/2 probability of drawing a permanent 5 star, and the remaining 1-p probability of not getting 5 stars.

When a permanent 5 star is drawn, the big guarantee mechanism is triggered. Each draw has a p probability of getting a 5 star in the current period, and the remaining 1-p probability is not a 5 star.

In addition, when 89 consecutive draws do not produce 5 stars, the next draw must produce 5 stars. In other words, if the big guarantee mechanism is not triggered, there is a 1/2 probability of drawing a current 5-star card and a 1/2 probability of drawing a permanent 5-star card. If the big guarantee mechanism has been triggered, the probability is 100%. Get 5 stars for the current period.

Now the probability p of drawing 5 stars is given. Mi Xiaoyou wants to draw a 5-star card for the current period. She wants to know how many times she expects to draw a card?

Enter description

A decimal p (0 < p < 1) represents the probability of winning 5 stars.

Output description

A floating point number representing the expected number of card draws. If the difference between your answer and the correct answer is no more than 10^-6, the answer is considered correct.

Example 1

enter

0.006

output

104.5497057

Problem analysis : A typical probability estimation problem is the same as breaking a rope. But this question is obviously more complicated. First of all, we have to divide into two situations. The first one is the five-star card drawn for the first time, which is the five-star card for the current period. The second one is the five-star card drawn for the first time, which is the permanent five-star card. The five-star card drawn for the second time is the five-star card for the current period. .

//第n次抽卡出5星的概率
double cal(int n, double p) {
	if (n < 90) {
		return pow(1 - p, n - 1) * p;
	}
	return pow(1 - p, n - 1);
}

int main() {
	double p;
	cin >> p;
	double result = 0;
	//第一次抽到5星就是当期五星
	for (int i = 1; i < 91; i++) {
		result += i * cal(i, p) / 2;
	}
	//第一次抽到五星是常驻五星,第二
	for (int i = 1; i < 91; i++) {
		for (int j = 1; j < 91; j++) {
			double p1 = cal(i, p) / 2;
			double p2 = cal(j, p);
			result += (i + j) * (p1 * p2);
		}
	}
	cout << result << endl;
	return 0;
}

The weight sum of all strings in bytes

Xiaohong defines the weight of a string as: the number of extremely long "continuous segments". The so-called extremely long "continuous segment" refers to a continuous substring with all the same characters as long as possible. For example, "1100111" has three consecutive segments: "11", "00" and "111", so the weight is 3.

Now Xiaohong has got a 01 string, and Xiaohong hopes you can help her find the sum of the weights of all substrings.

Enter description

The first line enters a positive integer n, which represents the length of the string.

The second line inputs a string of length n consisting only of '0' and '1' characters.

1<=n<=200000

Output description

A positive integer representing the sum of the weights of all substrings.

Example 1

enter

4
1101

enter

17

illustrate

The weights of the four substrings of length 1 are all 1.

In the substring of length 2, the weight of "11" is 1, and the weights of "10" and "01" are both 2.

In the substring of length 3, the weight of "110" is 2, and the weight of "101" is 3.

The substring "1101" of length 4 has a weight of 3.

The total weight is 1*4+1+2+2+2+3+3=17

Question analysis: This question is very simple to find the weight of a string. Just use a for loop and add 1 when there is a change. The question requires the sum of the weights of all substrings. When I first took the written test, I used two for loops to traverse all the substrings and then find the weights. I could only pass 30%, but later I found out that the master's DP was really awesome, and I was shocked for a while. The complexity is directly reduced to O(n).

Let’s talk about the idea of ​​dp in detail, which is difficult to understand. dp[i] represents the sum of the weights of all substrings ending with i . Then let's think about it, if s[i] == s[i - 1], that is, the current character is the same as the previous character, then as long as the substring ending with i - 1 character (dp[i - 1]), plus The weight of the i character will not change. Because the characters i and i - 1 in the table below are the same, adding the same character will definitely keep the weight unchanged. If you don’t understand, look at the definition of weight in the question. In the second case, if s[i] != s[i - 1], then any substring ending with i - 1 plus the i character will have their weight increased by 1. The specific dp process is shown below. code.

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main() {
    int n;
    cin >> n;
    string str;
    cin >> str;

    long long ans = 1;
    vector<long long> dp(n, 0);
    dp[0] = 1;

    for (int i = 1; i < n; i++) {
        if (str[i] == str[i - 1])
            dp[i] = dp[i - 1] + 1; //如果相同,那么以i结尾的子串权值等于i - 1结尾的子串权值 + i字符这个单独的子串
        else
            dp[i] = dp[i - 1] + i + 1; //如果不同,那么以i结尾的子串权值等于i - 1结尾的子串权值都 + 1, 再+i字符这个单独的子串

        ans += dp[i];
    }

    cout << ans << endl;

    return 0;
}

Byte necklace three beads mutually exclusive

Xiaohong arranged n beads in a row, and then strung them together to form a necklace (the connection is a ring, that is, the first and last beads are also adjacent), and any two adjacent beads The distance is 1. It is known that initially there are 3 beads that are red and the remaining beads are white.

Xiaohong has infinite magic power. She can control two adjacent beads on the necklace. Xiaohong hopes to use the minimum number of exchanges to make the minimum positive distance between Hongyi's two red beads small k. Can you help Xiaohong find the minimum number of exchanges?

Enter description

In the first line, enter a positive number t, which represents the number of inquiries.

For each query, five positive integers n, k, a1, a2, a3 are output, representing the total number of beads, the required distance between beads, and the positions of the three beads respectively.

1<=t<=10^4

1<=n<=10^9

1<=k,a1,a2,a3<=n

Ensure that the ai are different from each other.

Output description

Output t lines, and enter an integer in each line, representing the minimum number of exchanges. If the purpose cannot be accomplished, -1 is output.

Example 1

enter

2
6 2 1 2 3
5 2 1 3 4

output

2
-1

illustrate

In the first set of samples, the six beads are red, red, white, and white. The first operation exchanges the first and sixth beads, and the second operation exchanges the third and fourth beads.

The second group asked, there are 5 beads in total, including 3 red beads, so there will be two red beads adjacent to each other anyway, and it is impossible to satisfy the minimum distance between any two red beads of not less than 2.

Problem analysis: First, the positions of the three beads were given, but they didn’t know whether they were in order. They sorted them first, then found the distance between them, and put the three distances into the vector, which makes it easier to sort (because we each After changing the distance, you need to find the largest and smallest two). I was so stupid during the written test. Every time I judged which of the three numbers was less than k, if it was less than k, I would subtract one from the other two larger ones and add one to the smaller ones. In this way, only one position can be moved each time, and the time complexity times out. The specific operation should be to add and subtract the maximum and minimum simultaneously min(k - q[0], q[2] - k).

#include <iostream>
#include <string>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;
typedef long long ll;
vector<int> p(3);
vector<int> q(3);

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        int m, k, x, y, z;
        cin >> m >> k >> x >> y >> z;
        p[0] = x;
        p[1] = y;
        p[2] = z;
        sort(p.begin(), p.end());
        if (3ll * k > m)
        {
            cout << -1 << endl;
            continue;
        }
        q[0] = p[1] - p[0];
        q[1] = p[2] - p[1];
        q[2] = p[0] + m - p[2];
        sort(q.begin(), q.end());
        ll ans = 0;
        while (q[0] < k)
        {
            int now = min(k - q[0], q[2] - k);
            ans += now;
            q[2] -= now;
            q[0] += now;
            sort(q.begin(), q.end());
        }
        cout << ans << endl;
    }
    return 0;
}

Byte poker straight flush

Xiaohong has recently become obsessed with playing cards. There are four suits of playing cards: Spade, Heart, Diamond, and Club, and each card has a positive integer written on it. Xiaohong got a lot of cards and was ready to play the following game:

For each operation, randomly pick 5 cards from this pile, calculate the scores of these 5 cards, and then discard them (the discarded cards cannot be selected again).

For simplicity, this question only calculates the straight flush card type: that is, if the 5 cards taken out form a straight flush, 1 point will be awarded. No other card types are scored.

The so-called straight flush means that five cards are of the same suit, and after sorting, ai+1=a(i+l) is satisfied.

Xiaohong wants to know, after several operations, how many points can she get at most?

Please note that the same card type may appear multiple times!

Enter description

In the first line, enter an orthodox n, which represents the type of card in the deck (if the suit or value of the two cards is different, the type is considered to be different).

In the next n lines, enter two positive characters in each line: ai and cnti and one character ci. Represent the size, quantity and suit of each card respectively.

1<=n<=10^5

1<=ai,cnti<=10^9

ci∈{'s','H','D','C'}, represents the four suits of playing cards: spades, hearts, diamonds, and clubs.

Ensure that each type of card appears only once in the input.

Output description

An integer representing the maximum number of points that Xiaohong can obtain.

Example 1

enter

6
1 1 s
2 2 s
3 2 s
4 2 s
5 2 s
1 10 h

output

1

illustrate

You can get a straight flush: [1S, 2S, 3S, 4S, 5S]. Although there are 10 1s of hearts, they cannot form a flush with other cards.

Problem analysis: A straight flush can only appear in one suit. Then we divide the statistics into suits. After coming in, first put them into the dictionary according to the suit. The key is string suit and the value is a custom type. Because we need to know not only what values ​​this suit has, but also how many values ​​it has. So there is a set and a map in the custom type. At this time, we have a for loop. Get the values ​​of each suit, and how many of these values ​​there are. For loop on the values ​​in the set (set must be used because it is sorted by default), count the number of values, and the minimum number among the five values ​​from the current value to the current value + 4. This is based on the current value. The number of flushes at the beginning of the value, and the number in the map should be subtracted from the number of flushes. The specific code is as follows:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <set>

using namespace std;

struct node {
	set<int> st;
	unordered_map<int, int> cnt;
};
unordered_map<string, node> mp;
int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		int a, num;
		string c;
		cin >> a >> num >> c;
		mp[c].st.insert(a);
		mp[c].cnt[a] += num;
	}
	int result = 0;
	for (auto& col : mp) {
		node x1 = col.second;
		for (int start : x1.st) {
			int count = x1.cnt[start];
			for (int j = start + 1; j < start + 5; j++) count = min(count, x1.cnt[j]);
			result += count;
			for (int i = start; i < start + 5; i++) x1.cnt[i] -= count;
		}
	}
	cout << result << endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/slamer111/article/details/131429334