Blue Bridge Cup - 2016 7th C/C++ Zhenti [Provincial Competition] [Group B]

content

1. Number of briquettes (fill in the blank)

2. Birthday candles (fill in the blank)

3. Make up the formula (fill in the result)

4. Quick sort (code fill in the blanks)

5. Draw lots (fill in the code)

6. Fill in the squares (fill in the results)

7. Cut the stamp (fill in the blank)

8. Sum of Four Squares (Programming Question)

9. Swap bottles (programming questions)

10. Maximum scale (programming question)

11. Summary


1. Number of briquettes (fill in the blank)

There is a pile of briquettes, piled up in a triangular pyramid shape. Specifically:
1 on the first layer,
3 on the second layer (arranged in a triangle),
6 on the third layer (arranged in a triangle),
10 on the fourth layer (arranged in a triangle),

if there are a total of 100 layers, the total How many briquettes?

Please fill in the number representing the total number of briquettes.
Note: Your submission should be an integer, do not fill in any superfluous content or descriptive text.

Idea: It is easy to find the rule by analyzing the problem, the number of nth layers = the number of n-1 layers + n, you can use one variable to store the sum of the variables of each layer, and another variable to store the sum. Another method is to use Do this problem recursively. (Recursion plays a very important role in the algorithm, and it is not easy to understand. We try to change the loop we encounter to recursion, and over time we will master it)

Method 1: Loop

#include<iostream>
using namespace std;
int main()
{
	int n = 0;
	int sum = 0;
	for (int i = 1; i <= 100; i++)
	{
		n += i;
		sum += n;
	}
	cout << sum << endl;
	return 0;
}

Method 2: Recursion

#include<iostream>
using namespace std;
int f(int n)
{
	if (n == 1)
	{
		return 1;
	}
	return f(n - 1) + n;
}
int sum(int n)
{
	if (n == 1)
	{
		return 1;
	}
	return f(n) + sum(n - 1);
}
int main()
{
	cout << sum(100) << endl;
	return 0;
}

 Answer: 171700

2. Birthday candles (fill in the blank)

A certain gentleman has held a birthday party every year since a certain year, and every time he has to blow out the same number of candles as his age. Now counting, he blew out a total of 236 candles. Excuse me, at what age did he start birthday parties? Please fill in the age at which he started his birthday party. Note: Your submission should be an integer, do not fill in any superfluous content or descriptive text.

Ideas: This question is easier, just take enumeration (1-100) 

#include<iostream>
using namespace std;
int main()
{
	for (int i = 1;i <= 100; i++)
	{
		int sum = 0;
		for (int j = i; j <= 100; j++)
		{
			sum += j;
			if (sum == 236)
				cout << i << endl;
	 }
	}
	return 0;
}

3. Make up the formula (fill in the result)

insert image description here 

In this formula, AI represents the number 19, and different letters represent different numbers.

For example:
6+8/3+952/714 is one solution,
5+3/1+972/486 is another solution.

How many solutions are there to this equation?

Note: Your submission should be an integer, do not fill in any extra content or descriptive text.

Idea: This question is a very typical full permutation problem. Define an array a[10] to store numbers 1-9, and then perform full permutation through recursion and backtracking . This is a very general recursive function that can directly remember the template , you can apply it next time. Of course, you can also directly use next_permutation to perform full permutation. After full permutation, judge whether this formula satisfies the problem conditions, which is equal to 10; in order to better let readers understand the following check function, I will draw a picture to explain.

Code:

#include<iostream>
#include<algorithm>
using namespace std;
int ants = 0;
int a[] = { 1,2,3,4,5,6,7,8,9 };
bool check()
{
	int x = a[3] * 100 + a[4] * 10 + a[5];
	int y = a[6] * 100 + a[7] * 10 + a[8];
	if ((a[1] * y + a[2] * x) % (a[2] * y) == 0 && a[0] + (a[1] * y + a[2] * x) /( a[2] * y) == 10)
	{
		return true;
	}
	else {
		return false;
	}
}
/*递归回溯生成全排列,适应于无重复元素的情况*/
void f(int k)
{
	if (k == 9)//一种排列已经生成
	{
		if (check())//检查该排列是否符合题意
		{
			ants++;
	  }
	}
	//从k往后的每个数都可以放在k的位置
	for (int i = k; i < 9; i++)
	{
		{int temp = a[i]; a[i] = a[k]; a[k] = temp; }
		f(k + 1);//递归
		{int temp = a[i]; a[i] = a[k]; a[k] = temp; //回溯
		}
	}
}
int main()
{
	f(0);
	//可以直接用next_permutation来完成
	/*do {
		if (check())
		{
			ants++;
		}
	} while (next_permutation(a, a + 9));*/
	cout << ants << endl;
	return 0;
}

4. Quick sort (code fill in the blanks)

Sorting is often used in various situations.

Quick sort is a very common and efficient algorithm.
The idea is: first choose a "ruler",

Use it to pass the entire queue through a sieve,

To ensure that: no element on its left is greater than it, and no element on its right is less than it.
In this way, the sorting problem is split into two subintervals.

Then you can sort the subintervals separately.
The code below is an implementation, please analyze and fill in the missing code in the underlined part.

#include <stdio.h>
 
void swap(int a[], int i, int j)
{
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}
 
int partition(int a[], int p, int r)
{
    int i = p;
    int j = r + 1;
    int x = a[p];
    while(1){
        while(i<r && a[++i]<x);
        while(a[--j]>x);
        if(i>=j) break;
        swap(a,i,j);
    }
	______________________;
    return j;
}
 
void quicksort(int a[], int p, int r)
{
    if(p<r){
        int q = partition(a,p,r);
        quicksort(a,p,q-1);
        quicksort(a,q+1,r);
    }
}
    
int main()
{
	int i;
	int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
	int N = 12;
	
	quicksort(a, 0, N-1);
	
	for(i=0; i<N; i++) printf("%d ", a[i]);
	printf("\n");
	
	return 0;
}

Idea: We only need to analyze the relevant code according to the overall idea of ​​quick sort: while(i<r && a[++i]<x) ;Indicate that the left pointer finds a number larger than the target value, while(a[--j ]>x) ;Indicates that the right pointer finds a number smaller than the target value, f(i>=j) break ; Indicates that the formation of a small subscript i>=j will terminate. swap(a,i,j) ;Swap a[i] ,a[j] Even if the reverse order is restored, it conforms to the overall interval of small left and large right. After the above steps, we can confirm that a reverse order pair has been restored, and now the program proceeds to the step of replacing the standard value P. We will swap swap(a, p, j) because p is the standard value, a[j] is a value smaller than the standard value, and P is a[0] in the program, then we should replace P with the minimum value, so Replace with a[j].

Answer: swap(a,p,j);

5. Draw lots (fill in the code)

Planet X will send a 5-person observation group to Planet W. Among them: Country A can send up to 4 people. Country B can send up to 2 people. Country C can send up to 2 people. ....

So how many different combinations of countries will there be in the observation group sent to Star W?

The following program solves this problem. The array a[] is the maximum number of places each country can send. The program execution result is:

DEFFF

CEFFF

CDFFF

CDEFF

CCFFF

CCEFF

CCDFF

CCDEF

BEFFF

BDFFF

BDEFF

BCFFF

BCEFF

BCDFF

BCDEF

....

(以下省略,总共101行)

Ideas: In this question, you can see that there is a return if there is a return, and there are two for loops below, so we deduce that it is likely to be recursion, and then look down to see that the initial value of k is 0, and its termination condition is again k=N(6), indicating that k is increasing continuously, the initial value of m is 5, and the final output condition is indeed m=0, then it is inferred that m is constantly shrinking, and there are two variables that are constantly changing and then combining their forms, we then It must be a recursive expression. 

 1 #include <stdio.h>
 2 #define N 6
 3 #define M 5
 4 #define BUF 1024
 5 
 6 void f(int a[], int k, int m, char b[])
(数组a存放每个国家可以派出的人数;k表示国家个数,也作为深搜中外循环的条件;m表示剩下的人数;数组b存放情况的可能性)
 7 {
 8     int i,j;
 9     
10     if(k==N){ 
11         b[M] = 0;//这里是控制输出的字符串长度
12         if(m==0) printf("%s\n",b);
13         return;
14     }
15     
16     for(i=0; i<=a[k]; i++){//试着将k国家派出i个人
17         for(j=0; j<i; j++) b[M-m+j] = k+'A';
18         _____________;  //填空位置
19     }
20 }
21 int main()
22 {    
23     int  a[N] = {4,2,2,1,1,3};
24     char b[BUF];
25     f(a,0,M,b);
26     return 0;
27 }

 Answer: f(a,k+1,mi,b);  

6. Fill in the squares (fill in the results)

As shown in the figure, the following 10 grids are filled with numbers from 0 to 9. Requirements: Two consecutive numbers cannot be adjacent.
(Left and right, up and down, and diagonally adjacent to each other) How many possible filling schemes are there?
Please fill in an integer representing the number of scenarios.

 

 Idea: I saw 0-9 fill in this question. The first thing that came to my mind was the application of the full permutation problem . It may also be that this method has been used above, so it is more sensitive. We have summarized the template of this method above, and only need to change The check() function can be completed. Secondly, if there is really no way, explosive search is also a method, anyway, it is a fill-in-the-blank question.

Method 1: Full arrangement

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int ants ;
int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
bool check()
{
	if (abs(a[0] - a[1]) == 1 ||
		abs(a[0] - a[3]) == 1 ||
		abs(a[0] - a[4]) == 1 ||
		abs(a[0] - a[5]) == 1 ||

		abs(a[1] - a[2]) == 1 ||
		abs(a[1] - a[4]) == 1 ||
		abs(a[1] - a[5]) == 1 ||
		abs(a[1] - a[6]) == 1 ||
		abs(a[2] - a[5]) == 1 ||
		abs(a[2] - a[6]) == 1 ||
		abs(a[3] - a[4]) == 1 ||
		abs(a[3] - a[7]) == 1 ||
		abs(a[3] - a[8]) == 1 ||
		abs(a[4] - a[5]) == 1 ||
		abs(a[4] - a[7]) == 1 ||
		abs(a[4] - a[8]) == 1 ||
		abs(a[4] - a[9]) == 1 ||
		abs(a[5] - a[6]) == 1 ||
		abs(a[5] - a[8]) == 1 ||
		abs(a[5] - a[9]) == 1 ||
		abs(a[6] - a[9]) == 1 ||
		abs(a[7] - a[8]) == 1 ||
		abs(a[8] - a[9]) == 1)
		return false;
	return true;
}
void f(int k)
{
	if (k == 10)
	{
		if (check())
		{
			ants++;
		}
		return;
	}
	for (int i = k; i < 10; i++)
	{
		{int temp = a[i]; a[i] = a[k]; a[k] = temp; }
		f(k + 1);
		{int temp = a[i]; a[i] = a[k]; a[k] = temp; }
	}
}
int main()
{
	/*do {
		if (check())
		{
			ants++;
		}
	} while (next_permutation(a, a + 10));*/
	f(0);
	cout << ants << endl;
	return 0;
}

Method 2: violent search

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

int a[4][5],visit[10];
int dx[4]={-1,-1,-1,0};
int dy[4]={0,1,-1,-1};
int sum;

bool check(int x,int y,int n){
    for(int i=0;i<4;i++){
        int xx=x+dx[i];
        int yy=y+dy[i];
        if(xx<3&&xx>=0&&yy>=0&&yy<4){
            if(abs(a[xx][yy]-n)==1)
                return false;
        }
    }
    return true;
}

void dfs(int x,int y){
    if(x==2&&y==3){
        sum++;
        return;
    }
    for(int i=0;i<10;i++){
        if(visit[i]==0&&check(x,y,i)){
            visit[i]=1;
            a[x][y]=i;
            if(y+1<4)
                dfs(x,y+1);
            else
                dfs(x+1,0);//另起一行
            visit[i]=0;
        }
    }
}

int main(){
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            a[i][j]=-20;
    dfs(0,1);
    cout<<sum;
    return 0;
}

Answer: 1580 

7. Cut the stamp (fill in the blank)

Cut stamps 

As shown in [Picture 1.jpg], there are 12 stamps of the 12 zodiac signs linked together. 
Now you have to cut 5 out of them, and the requirements must be connected. 
(Just connecting one corner is not considered to be connected.) 
For example, in [Figure 2.jpg] and [Figure 3.jpg], the part shown in pink is a qualified clipping. 

Please count how many different clipping methods there are. 

Please fill in an integer representing the number of scenarios. 
Note: Your submission should be an integer, do not fill in any superfluous content or descriptive text.

 

Ideas: This question is easy to think of DFS deep search to do, but there will be problems with deep search alone, and a "T" shape will appear, and deep search cannot be rightward and i downward at the same time. Therefore, we should use full array, and then put it Put it into a two-dimensional array, use deep search to determine whether it has connectivity, and then go directly to the code: (Note that you can't complete the full arrangement by hand here, you need to use next_permutation because the handwritten full arrangement will repeat, and this function will generate no repeat)

#include<iostream>
#include<algorithm>
using namespace std;
int ants;
int a[] = { 0,0,0,0,0,0,0,1,1,1,1,1 };
void dfs(int g[3][4],int x, int y)
{
	g[x][y] = 0;
	if (x - 1 >= 0 && g[x - 1][y] == 1)dfs(g, x - 1, y);
	if (x + 1 <= 2 && g[x + 1][y] == 1)dfs(g, x + 1, y);
	if (y - 1 >= 0 && g[x][y - 1])dfs(g, x, y - 1);
	if (y + 1 <= 3 && g[x][y + 1])dfs(g, x, y + 1);

}
bool check()
{
	int g[3][4];
	//将某个排列银蛇到
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			if (a[i * 4 + j] == 1)g[i][j] = 1;
			else   g[i][j] = 0;
		}
	}
	int cnt = 0;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			if (g[i][j] == 1)
			{
				dfs(g,i, j);
				cnt++;
			}
		}
	}
	return cnt == 1;
}
int main()
{
	do {
		if (check())
		{
			ants++;
		}
	} while (next_permutation(a, a + 12));
	cout << ants << endl;
	return 0;
}

Answer: 116 

8. Sum of Four Squares (Programming Question)

The Four Sum of Squares Theorem, also known as Lagrange's Theorem: Every positive integer can be expressed as the sum of squares of at most four positive integers. If you include 0, it can be expressed as the sum of the squares of 4 numbers. For example: 5 = 0^2 + 0^2 + 1^2 + 2^2 7 = 1^2 + 1^2 + 1^2 + 2^2 (the ^ symbol means power) for a given For positive integers, there can be multiple representations of the sum of squares. Asks you to sort 4 numbers: 0 <= a <= b <= c <= d. And sort all possible representations in ascending order according to a, b, c, d as the joint primary key, and finally output the first representation. The program input is a positive integer N (N<5000000), and it is required to output 4 non-negative integers, sorted from small to large, separated by spaces

For example, input:
5
then the program should output:
0 0 1 2

For another example, input:
12
, the program should output:
0 2 2 2

For another example, input:
773535
, the program should output:
1 1 267 838

Resource convention:
peak memory consumption < 256M
CPU consumption < 3000ms

Please output strictly according to the requirements, and do not superficially print superfluous content like: "Please enter...". All code is placed in the same source file, after debugging, copy and submit the source code.

Note: The main function needs to return 0
Note: Only use the ANSI C/ANSI C++ standard, do not call special functions that depend on the compilation environment or operating system.
Note: All dependent functions must be explicitly #include <xxx> in the source file, and common header files cannot be omitted through project settings.

When submitting, take care to select the desired compiler type.

Ideas: The first thing we think of is violent enumeration. This method has high time complexity and will cause running timeout, but we can get some points. We need to find a way to reduce the time complexity. For this problem, we can reduce the time complexity of the for loop. times to reduce the time complexity.

Code:

#include<iostream>
#include<cmath>
#include<map>
using namespace std;
int main()
{
	int n;
	cin >> n;
	map<int, int> m;
	for (int c = 0;c* c <= n / 2; c++)
	{
		for (int d = c; c*c+d*d <= n; d++)
		{
			if (m.find(c*c + d*d) == m.end()) {
				m[c*c + d*d] = c;
			}
		}
	}
	for (int a = 0; a*a <= n / 4; a++)
	{
		for (int b = a; a*a+b*b <= n / 2; b++)
		{
			if (m.find(n - a*a -  b*b) != m.end())
			{
				int c = m[n - a*a - b*b];
				int d = (int)sqrt(n - a*a - b*b - c*c);
				cout << a << " " << b << " " << c << " " << d << endl;
				return 0;
			}
		}
	}
	return 0;
}

9. Swap bottles (programming questions)

There are N bottles, numbered 1~N, on the shelf.

For example there are 5 bottles:
2 1 3 5 4

Ask to pick up 2 bottles at a time and swap their positions.
After several times, the serial number of the bottle is:
1 2 3 4 5

For such a simple case, obviously, at least 2 swaps are required to reset.

What if there were more bottles? You can solve it programmatically.

The input format is two lines:
the first line: a positive integer N (N<10000), indicating the number of bottles. The
second line: N positive integers, separated by spaces, indicating the current arrangement of the bottles.

The output data is a row of a positive integer, indicating how many times to exchange at least to complete the sorting.

For example, enter:
5
3 1 2 5 4

The program should output:
3

For another example, enter:
5
5 4 3 2 1

The program should output:
2

Resource convention:
peak memory consumption < 256M
CPU consumption < 1000ms

Please output strictly according to the requirements, and do not superficially print superfluous content like: "Please enter...".

All code is placed in the same source file, after debugging, copy and submit the source code.

Note: The main function needs to return 0
Note: Only use the ANSI C/ANSI C++ standard, do not call special functions that depend on the compilation environment or operating system.
Note: All dependent functions must be explicitly #include <xxx> in the source file, and common header files cannot be omitted through project settings.

When submitting, take care to select the desired compiler type.

Idea: This question can be done by bubble sort, reverse order, etc., but the efficiency is relatively low, we take this question, first create an array, and then judge whether a[i]==i is true, if not, use pos to find i position, and then swap it;

Code:

#include<iostream>
using namespace std;
int a[10001];
int n;
int ants;
int pos(int x)
{
	for (int i = 1; i <= n; i++)
	{
		if (a[i] == x)
		{
			return i;
		}
	}
	return -1;
}
void swap(int i, int j)
{
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}
int main()
{

	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	for (int i = 1; i <= n; i++)
	{
		if (a[i] == i)
		{
			continue;
		}
		else {
			swap(pos(i), i);
			ants++;
		}
	}
	cout << ants << endl;
	return 0;
}

10. Maximum scale (programming question)

A certain Grand Prix on Planet X has M-level rewards. The bonus for each level is a positive integer.

Also, the ratio between two adjacent levels is a fixed value.

That is to say: the bonus numbers of all levels form a proportional sequence.

For example: 16,24,36,54

Its equivalent ratio is: 3/2

Now, we've randomly surveyed some of the winners' prize numbers.

Please calculate the maximum possible equivalent value based on this.

Input format:

The first line is a number N (N<=100), indicating that the next line contains N positive integers

The second line contains N positive integers Xi (Xi<1 000 000 000 000), separated by spaces. Each integer represents the amount of bonus paid to someone surveyed

Request output:

A fraction of the form A/B requires A and B to be relatively prime. represents the largest possible scaling factor

The test data ensures that the input format is correct and that the maximum scale exists.

enter 3
1250 200 32
4
3125 32 32 200
3
549755813888 524288 2
output 25/4 5/2 4/1

 Idea: find the common ratio of the proportional sequence, Xi < 10^12, sort the items first, divide them in pairs, and divide them. As long as the result of each calculation is greater than 1, the last remaining is the greatest common ratio. N=100, O(N*N) is acceptable. It is necessary to pay attention to deduplication and the case where the common ratio is 1.

#include <cstdio>
#include <algorithm>
struct fs {
    __int64 fz, fm;
    bool operator == (const fs &B)const {
        if (B.fz != fz || B.fm != fm) return 0;
        return 1;
    }
}data[105];
__int64 rd[105];
__int64 GCD(__int64 a, __int64 b) {
    __int64 c;
    while (c = a%b) a = b, b = c;
    return b;
}
fs slv(fs a, fs b) {
    if (a == b) return a;
    __int64 gcd;
    gcd = GCD(a.fz, b.fz);
    a.fz /= gcd; b.fz /= gcd;
    gcd = GCD(a.fm, b.fm);
    a.fm /= gcd; b.fm /= gcd;
    a.fz *= b.fm;
    b.fz *= a.fm;
    if (a.fz > b.fz) a.fm = b.fz;
    else a.fm = a.fz, a.fz = b.fz;
    return a;
}
int main() {
    int i, j, n;
    scanf("%d", &n);
    for (i = 0; i < n; ++i) scanf("%I64d", rd + i), data[i].fm = 1;
    std::sort(rd, rd + n);
    for (i = j = 0; i < n; ++i) if (rd[i] != rd[i + 1]) data[j++].fz = rd[i];
    for (n = j - 1; n; --n) {
        for (i = 0; i < n; ++i) data[i] = slv(data[i], data[i + 1]);
    }
    if (j == 1) puts("1/1");
    else printf("%I64d/%I64d", data[0].fz, data[0].fm);
    return 0;
}

11. Summary

01 Simple calculation of the number of briquettes      02 Birthday candle  arithmetic sequence summation 03  Arrangement of arithmetic formulas  04 Quick sort naked questions 05        Recursion by lottery   06 Full arrangement of squares and numbers + check 07 Full arrangement of cut stamps      + dfs to find connected blocks in the matrix 08 Four Square sum    enumeration + optimization (hash cache) 09 swap bottle greedy 10 maximum scale   math, proportional sequence preprocessing
   
      
      
   
      
   
 
     
   

Guess you like

Origin blog.csdn.net/m0_58367586/article/details/123709742