I've never seen such a simple divide and conquer problem...

Posted by DataRater on Wed, 02 Feb 2022 05:01:42 +0100

There are several problems in SCAU computational intelligence, so I specially make a summary.

 

1142 soldiers on patrol

Description

have N Soldiers stood in a line, Now we need to select several soldiers to send for reconnaissance.
In order to choose the right soldiers, Perform the following operations several times: If there are more than three soldiers in the queue, Then remove all soldiers standing in odd positions, 
Or eliminate all soldiers standing in an even number of positions. Until there are no more than three soldiers, they will be sent to reconnaissance. Statistics are now required to follow this method,
How many different soldier combinations can there be for exactly three soldiers to scout.

notes: The situation of less than three soldiers obtained according to the above method is not counted.

1 <= N <= 2 To the 32nd power of-1

 

Input format

There are multiple lines (there may be hundreds of lines, try to optimize the code), and one number per line N,The last line is 0

 

Output format

Number for each line N,Output for N Number of schemes

Until there are no numbers

 

sample input

10
4
0

sample output

2
0

Idea:

It is known that every time we remove the soldiers in odd or even positions in the queue, there are three cases in total according to the meaning of the question. When the last number of soldiers is n==3, it is a legal result, and when n < 3, it is an illegal result. When n > 3, we can continue to score.

Then there is another problem about the parity of N. if it is an even number, removing the odd number and even number is to remove half of the people. If the number is the same, the result will be multiplied by 2 directly. If it is an odd number, half is n/2 and the other half is n/2+1. Add it.

code:

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

int dc(int n) {
	if (n == 3)return 1;
	if (n < 3)return 0;
	if (n % 2 == 0)return 2 * dc(n / 2);
	else { return dc(n / 2) + dc(n / 2 + 1); }
}
int main() {
	ios::sync_with_stdio(false);
	int n; cin >> n;
	while (n) {
		cout << dc(n)<<endl;
		cin >> n;
	}


}

18441 lazy soldiers

Description

have N Soldiers stood in a line, Now we need to select several soldiers to send for reconnaissance.
In order to choose the right soldiers, Perform the following operations several times: If there are more than three soldiers in the queue, Then remove all soldiers standing in odd positions, 
Or eliminate all soldiers standing in an even number of positions. Until there are no more than three soldiers, they will be sent to reconnaissance. There is a "smart" soldier,
Often choose to stand in the appropriate initial position to successfully avoid being selected for reconnaissance. This attracted the attention of instructor Chen. Instructor Chen wants you to write a program,
When the number of soldiers is given, it is impossible to output how many soldiers in different positions can be selected to patrol.

notes: If you get less than three soldiers according to the above method, you don't have to patrol.

1 <= N <= 21 Hundred million

Input format

There are multiple lines (there may be hundreds of lines, please optimize the code as much as possible), and each line has a number N,The last line is 0

Output format

Number for each line N,Number of locations that cannot be selected to patrol

Until there are no numbers

 

sample input

10
6
0

sample output

4
0

Idea:

Most of the ideas of this question are the same as those of the above one, only one thing needs to be changed.

When the last n==3, all soldiers have to patrol. Naturally, the number of positions that cannot be selected is 0;

When n < 3, the number that cannot be selected is n.

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

int dc(int n) {
	if (n == 3)return 0;
	if (n < 3)return n;
	if (n % 2 == 0)return 2 * dc(n / 2);
	else { return dc(n / 2) + dc(n / 2 + 1); }
}
int main() {
	ios::sync_with_stdio(false);
	int n; cin >> n;
	while (n) {
		cout << dc(n)<<endl;
		cin >> n;
	}


}

18442 lazy soldier 2

Description

have N Soldiers stood in a line, Now we need to select several soldiers to send for reconnaissance.
In order to choose the right soldiers, Perform the following operations several times: If there are more than three soldiers in the queue, Then remove all soldiers standing in odd positions, 
Or eliminate all soldiers standing in an even number of positions. Until there are no more than three soldiers, they will be sent to reconnaissance. There is a "smart" soldier,
Often choose to stand in the appropriate initial position to successfully avoid being selected for reconnaissance. This attracted the attention of instructor Chen. Instructor Chen wants you to write a program,
When the number of soldiers is given, the lowest numbered position that cannot be selected to patrol is output (if there is no position that cannot be selected, 0 is output).

notes: If you get less than three soldiers according to the above method, you don't have to patrol.

1 <= N <= 100000

 

Input format

There are multiple lines (no more than 20 lines), one number per line N,The last line is 0

Output format

Number for each line N,Number of locations that cannot be selected to patrol

Until there are no numbers

 

sample input

9
6
0

 

sample output

2
0

Idea:

The general idea is the same, but our return value is changed to the number at the beginning of the sequence.

We can think like this. For a sequence, when n==3, we can't be lazy. We return a huge value. When n < 3, we can be lazy. We return the beginning number. When n > 3, we continue to score. Each time odd or even numbers are removed, two sequences will be generated. Finally, there will be two return values. We can take the minimum.

The difficulty is how to record the number of the first position of the sequence obtained by removing odd or even. Through observation and thinking, we can find that for the original sequence L, the number of the first sequence L1 after removing the even number remains unchanged, while for the sequence L2 after removing the odd number, the number of the first sequence L2 is the first number of the original sequence L, first+k; This k is a multiplication constant, k*=2; Roughly prove that because we remove half of the data every time, the number interval between two adjacent positions will be twice as long as before. Or, if you fill in a complete binary tree, you can find the corresponding relationship in theory, and I won't....

It is worth mentioning that the parity of n should not be discussed? Yes, but it's not necessary. The purpose of discussing parity is to reduce the branches of binary tree and reduce the time overhead.

Originally for the first and second questions. Whether n is odd or even, when n > 3, we can write f((n+1)/2)+f(n/2); Just,

We find that when n is even, the length of the two sequences is the same, so the result is the same. Just the third question, although the length of the sequence is the same, the number at the beginning is also different.

code:

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#define MAX 2147483647
int dc(int n,int first,int step) {
	if (n == 3)return MAX;
	if (n < 3)return first;
	return min(dc((n + 1) / 2, first, step*2) , dc(n/2,first+step,step*2));
}
int main() {
	ios::sync_with_stdio(false);
	int n; cin >> n;
	while (n) {
		cout << dc(n, 1, 1) % MAX << endl;
		cin >> n;
	}


}

If there is a mistake, please advise!

Topics: Algorithm