The way for beginners to brush questions (week 2)

According to the Luogu questionnaire, I plan to brush a violent enumeration XD this week

Although it is a violent enumeration, the timeout is still timeout (sweat ~)

First of all, a method of violent enumeration is to use deep search to solve repeated operations

Just like the following combinatorial number topic

Combined output - Luogu

Without knowing how many times to repeat this question, there are two ways. One is because the n given by this question is not large, you can list all the situations. The second is the normal deep search logic. Marking and restoring operations are very important steps in dfs. Here is my code:

#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[105],b[105];
void dfs(int k,int m,int n) {//k represents the current number of layers and n represents the maximum number of layers
	if (k > n) {//Output array when it is greater than the maximum number of layers
		for (int i = 1; i <= n; i++) {
			cout << setw(3) << a[i];
		}
		cout << endl;
		return;
	}
	for (int i = 1; i <= m; i++) {
		if (b[i] == 0 && i > a[k - 1]) {
			a[k] = i;
			b[i] = 1;
			dfs(k + 1, m, n);
			b[i] = 0;
		}
	}
}
int main() {
	int n, m;
	cin >> m >> n;
	dfs(1, m, n);
	return 0;
}

Then there is a topic related to full arrangement. After mastering STL, you can write it immediately, but Ben Xiaobai hasn't learned this yet, so he still uses dfs. However, it's really not easy to understand this problem. The first thing to know is the arrangement of full arrangement from small to large, which is to check the number that can be increased from back to front, that is, find a number smaller than the number in the next digit, Then, search for the number that can be added from back to front, that is, the first number larger than this number. After switching, reverse all the back of the previous number. This process is the process of full arrangement i to i+1

This is exactly the other two methods corresponding to this type of questions, namely violent operation and efficient calculation using functions

The title is as follows

 [NOIP2004 popularity group] Martians - Rogue

#include<iostream>
#include<stdio.h>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[1000005];
int m, n;
void myincrease(int m) {
	while (m--) {
		int i, j;
		for (i = n - 1; i >= 1; i--) {
			if (a[i] < a[i + 1]) {
				break;
			}
		}
		for (j = n; j >= i; j--) {
			if (a[j] > a[i]) {
				break;
			}
		}
		int t = a[j];
		a[j] = a[i];
		a[i] = t;
		++i;
		j = n;
		while (i < j) {
			t = a[i];
			a[i] = a[j];
			a[j] = t;
			i = i + 1;
			j = j - 1;
		}
	}
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	myincrease(m);
	for (int i = 1; i <= n-1; i++) {
		cout << a[i] << " ";
	}
	cout << a[n];
	return 0;
}

Of course, I also learned the manual STL method later, that is, the above operation can be realized by a function, that is

#include<iostream>
#include<stdio.h>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[1000005];
int m, n;
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= m; i++) {
		next_permutation(a + 1, a + 1 + n);
	}
	for (int i = 1; i <= n-1; i++) {
		cout << a[i] << " ";
	}
	cout << a[n];
	return 0;
}

Blood loss okay~

Next is the question of standing in line. It's not difficult. It's easy to think of the logic of deep search, but! However, I have always reported two errors in this problem, and I don't know why. It took me a long time to find that when there is only one person in the team, special treatment should be carried out, because I calculated the method twice. I'm really drunk~

First Step (Luogu)

#include<iostream>
#include<stdio.h>
#include<iomanip>
#include<algorithm>
using namespace std;
char a[500][500];
int m, n, z;
int sum = 0;
void dfs(int i, int j, int k, int w) {
	if (k >= z) {
		++sum;
		return;
	}
	if (i<1 || j<1 || i>m || j>n)return;
	if (a[i + 1][j] == '.' && w == 1)dfs(i + 1, j, k + 1, 1);
	if (a[i][j + 1] == '.' && w == 2)dfs(i, j + 1, k + 1, 2);
	return;
}
int main() {
	cin >> m >> n >> z;//m rows n columns
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> a[i][j];
		}
	}
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i][j] == '.') {
				dfs(i, j, 1, 1);
				dfs(i, j, 1, 2);
			}
		}
	}
	if (z == 1)sum = sum / 2;
	cout << sum;
	return 0;
}

By the way, deep search without restore operation is really comfortable, ha ha~

The biggest problem with violent enumeration is that problems like violent enumeration cannot be violent enumeration

for example [USACO1.5] palindrome Prime Palindromes - rogu

I am proud of the violence enumeration results and only got 66 points, woo woo

The reason is that the last three times out

Therefore, this method should be used with caution! Use with caution!

Of course, if you don't have any other ideas like me, you'll have to fight in this way~

It seems that violent enumeration can also be used for this problem. According to other leaders, the maximum number that meets the conditions in this interval is 99899

Then it doesn't seem to time out

In a word, there are other methods or other methods XD

Next is a typical skill enumeration problem

Demon dream stick - Luogu

Then, at the beginning, I spent five minutes writing the most violent enumeration

	sort(a + 1, a + 1 + n);
	for (int i = 1; i <= n - 1; i++) {
		if (a[i] == a[i + 1]) {
			for (int j = 1; j <= i; j++) {
				for (int k = 1; k <= i; k++) {
					if (a[j] + a[k] == a[i]) {
						sum++;
					}
				}
			}
		}
	}

  Ha ha, sure enough

As expected, it can be said that

Therefore, it is natural to think about how to optimize. The most obvious optimization idea must be to reduce the number of cycles. At this time, it is much better to mark with an array.   Moreover, you can't browse through the array subscript, which is too time complex.

#include<iostream>
#include<stdio.h>
#include<iomanip>
#include<algorithm>
#include<math.h>
using namespace std;
int m, n;
int a[1000000], b[1000000];
int mymin = 1e9, mymax = -1;
int k = 1e9 + 7;
int main() {
	int n;
	cin >> n;
	long long sum = 0;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		mymin = min(mymin, a[i]);
		mymax = max(mymax, a[i]);
		b[a[i]]++;//The number of occurrences of this length
	}
	for (int i = mymin + 1; i <= mymax; i++) {
		if (b[i] > 1) {//This length occurs twice or more
			for (int j = mymin; j <= i / 2; j++) {
				if (b[i - j] >= 1 && b[j] >= 1) {//A stick of these two lengths
					if (j == i - j && b[j] > 1) {
						sum = sum + ((b[i] * (b[i] - 1) >> 1) % k * (b[j] * (b[j] - 1) >> 1) % k) % k;
					}
					else if (j != i - j) {
						sum = sum + ((b[i] * (b[i] - 1) >> 1) % k * b[j] * b[i - j]) % k;
					}
					sum = sum % k;
				}
			}
		}
	}
	cout << sum;
	return 0;
}

This is the last code, for reference only XD

To sum up, the main ideas of violence enumeration include deep search, typing tables, skillfully using enumeration, STL and other methods. So, see you next time~

Tags: C++ Algorithm

Posted on Sat, 25 Sep 2021 02:55:01 -0400 by the_lynx123