71. Joseph's Problem
This is a 17th century French mathematician gaspa told the story of the number of games: 15 believers and 15 non-believers in deep sea distress, half of the people must be put into the sea, and the rest of the people can survive, so I thought of a way: 30 people in a circle, from the first person to report, the ninth person throws him into the sea and repeats until only 15 people exist. Ask how to arrange the law so that every time you invest in the sea, it will be non-believers.
* Problem analysis and Algorithm Design
Joseph's problem is not difficult, but there are many ways to solve it. There are also many forms of questions. Here is an implementation method.
30 people in the question circle, which inspires us to use a cyclical chain. The structure array can be used to form a loop chain. There are two members in the structure. One is the pointer to the next person to form a ring chain. The other is the mark of whether the person is thrown down the sea. The other is 1, indicating that the person is still on the ship. From the first person, count the person who has not yet dropped the sea. When the number is 9, the mark in the structure is changed to 0, indicating that the person has been dropped to the sea. In this way, the cycle is counted until 15 people are dropped.
* Program description and comment
# Include <stdio. h>
Struct Node
{
Int nextp;/* pointer to the next person (array subscript of the next person )*/
Int no_out;/* indicates whether the flag is dropped from the sea. 1: not dropped to the sea. 0: dropped to sea */
} Link [31];/* 30 people, no use of element 0 */
Int main ()
{
Int I, J, K;
Printf ("the original circle is (+: pagendom, @: Christian):/N ");
For (I = 1; I <= 30; I ++)/* initialize the structure array */
{
Link [I]. nextp = I + 1;/* The Pointer Points to the next person (array element subscript )*/
Link [I]. no_out = 1;/* indicates that all people are on the ship */
}
Link [30]. nextp = 1;/* 30th the pointer of a person points to the first person to form a ring */
J = 30;/* j: points to the processed array elements, starting from the person indicated by link [I */
For (I = 0; I <15; I ++)/* I: Counter of the number of people who have dropped the sea */
{
For (k = 0;)/* K: determines which person is dropped to the sea counter */
If (k <15)
{
J = link [J]. nextp;/* modify the pointer and remove a person */
K + = link [J]. no_out. Marked as 0 */
}
Else break;/* Stop counting when the count reaches 15 */
Link [J]. no_out = 0;/* set the mark to 0, indicating that the person has been dropped to the sea */
}
For (I = 1; I <= 30; I ++)/* output result */
Printf ("% C", link [I]. no_out? '@': '+');/* +: Dropped to the sea, @: On the ship */
Printf ("/N ");
}
* Running result
The original circle is (+: pagandom, @: Christian ):
+++ + + + ++ +
(+ "Non-believers who are dropped to the sea @: those who stay on the ship for Life)
* Questions
There are n Children in a circle and are numbered in sequence. The teacher specifies to report the number of children starting from the MTH, and report the number to the second child so that the children can be listed. Then, the next child continues to report data, and the number of the second child is counted so that all the children are listed. Query the sequence of Children columns.
72. Stamp combination
A person has four 3-cent stamps and three 5-cent stamps. How many different kinds of postage can be obtained with one or more of these stamps?
* Problem analysis and Algorithm Design
The problem is analyzed in mathematics. The postage composed of stamps with different numbers and denominations can be calculated using the following formula:
S = 3 * I + 5 * j
Among them, I is the number of three-point mails, and J is the number of five-point mails.
According to the requirements of the question, you can take 0, 1, 2, 3, and 4 stamps with 3 points, and 0, 1, 2, and 3 stamps with 5 points. The postage after the combination of different numbers of postage labels with different denominations can be obtained through the exhaustive method.
* Program description and comment
# Include <stdio. h>
Int A [27];
Int main ()
{
Int I, J, K, S, N = 0;
For (I = 0; I <= 4; I ++)/* I: Number of three-part stamps */
For (j = 0; j <= 3; j ++)/* j: number of stamps with 5 points */
{
S = I * 3 + J * 5;/* calculate the composite stamp face value */
For (k = 0; A [k]; k ++)/* check whether the same postage exists */
If (S = A [k]) break;
If (! A [k] & S)/* If the same postage is not found, the request is saved to the array */
{
A [k] = s; n ++;
}
}
Printf ("% d kinds:", n);/* output result */
For (k = 0; A [k]; k ++)
Printf ("% d", a [k]);
Printf ("/N ");
}
* Running result
19 kinds: 5 10 15 3 8 13 18 6 11 16 21 9 14 19 24 12 17 22 27
73. The number represents 1 ~ 5 Positive Integers of 23
It is known that the sum of the five non-identical positive integers is 23, and several of them can be selected from these five numbers to represent all the natural numbers from 1 to 23. What are the five numbers?
* Problem analysis and Algorithm Design
From the perspective of computer programming, we can use the exhaustive method to break down 23, and then determine whether the five numbers can represent all integers between 1 and 23.
* Program description and comment
# Include <stdio. h>
Int main ()
{
Int A, B, C, D, E, I, J, K, L, M, X, Count = 0, f = 0;/* F: the number of 5 shards can be 1 ~ 23 mark */
Printf ("there are following possble result:/N ");
For (A = 1; A <= 23; A ++)/* Splits 23 into five numbers: A, B, C, D, and E */
For (B = 1 + A; B <= 23-A; B ++)
For (C = 1 + B; C <= 23-a-b; C ++)
For (D = 1 + C; D <= 23-a-b-c; D ++)
{
F = 1;
If (E = 23-a-b-c-d)> D)
For (F = 0, x = 1; x <24 &&! F; X ++)/* determines whether 5 numbers can represent 1 ~ 23 */
For (F = 1, I = 0; I <2 & F; I ++)/* select all the five numbers of samples */
For (j = 0; j <2 & F; j ++)
For (k = 0; k <2 & F; k ++)
For (L = 0; L <2 & F; l ++)
For (m = 0; m <2 & F; m ++)
If (x = A * I + B * j + C * k + D * L + E * m) f = 0;
If (! F) printf ("[% d]: % d/N", ++ count, A, B, C, D, E );
}
}
* Running result
There are following possble result:
[1]: 1 2 3 5 12
[2]: 1 2 3 6 11
[3]: 1 2 3 7 10
[4]: 1 2 4 5 11
[5]: 1 2 4 6 10
[6]: 1 2 4 7 9
74. 1 ~ Four 40-pound weights
French mathematician metziac raised a question in his famous "Digital combo game" (1962): a merchant has a 40-pound weight, one day, I accidentally broke the weight into four parts. Then the merchant claimed that each piece of weight was a whole pound, and he found that the four fragments could be weighed between 1 and 40 lbs on an equal footing. What are the weights of these four fragments?
* Problem analysis and Algorithm Design
This question is the development of the previous question. The condition given in the question is "On the Tianping", which means that the same weight can be placed on either the left side of the balance or the right side of the balance. If heavy objects can only be placed on the left side of the balance, when the balance is:
Weight + weight on the Left = weight on the right
Therefore, you can obtain the following information:
Weight = weight of the right weight-weight of the left
During programming, you only need to use the above formula to make "weight sum on the right-weight sum on the left" indicate all weights between 1 and 40. It should be noted in programming: how to use a simple method to indicate whether a weight is on the left of the balance, on the right of the balance, or is not used at all.
The following procedures use 1,-1, and 0 to indicate the above three situations, please understand.
* Program description and comment
# Include <stdio. h>
# Include <math. h>
Int main ()
{
Int weight1, weight2, weight3, weight4, D1, D2, D3, D4, X, flag;/* flag: match the meaning of the question */
Printf ("the weight is broke up as following 4 pieces :");
For (weight1 = 1; weight1 <= 40; weight1 ++)/* Splits 40 into four portions */
For (weight2 = weight1 + 1; weight2 <= 40-weight1; weight2 ++)
For (weight3 = weight2 + 1; weight3 <= 40-weight1-weight2; weight3 ++)
If (weight4 = 40-weight1-weight2-weight3)> = weight3)
{
For (flag = 1, x = 1; x <41 & flag; X ++)/* determines whether 1 ~ can be claimed ~ All weights between 40 */
For (flag = 0, d1 = 1; D1>-2; D1-)/* place the heavy objects on the left of the balance */
For (d2 = 1; D2>-2 &&! Flag; D2-)/* 1: The weight is on the right of the balance */
For (D3 = 1; D3>-2 &&! Flag; D3-)/* 0: this weight is not required */
For (D4 = 1; D4>-2 &&! Flag; D4-)/*-1: The weight is on the left of the balance */
If (x = weight1 * D1 + weight2 * D2 + weight3 * D3 + weight4 * D4)
Flag = 1;
If (FLAG) printf ("% d/N", weight1, weight2, weight3, weight4 );
Flag = 0;
}
}
* Running result
The weight is broke up as following 4 pieces: 1 3 9 27
75.10 children divided into candy
Ten children are divided into a circle of candy. The teacher gives the first child 10, the second child 2, the third child 8, and the fourth child 22, there are 16 fifth Children, 4 Sixth children, 10 Seventh children, 6 Eighth children, 14 Ninth children, and 20 tenth children. Then all the children give half of the sugar in their hands to the children on the right at the same time. People with odd sugar blocks may ask the teacher for one. Q: How many times have the same amount of sugar in your hands? How much sugar does each have?
* Problem analysis and Algorithm Design
The sugar splitting process described in the question is a mechanical repetitive process, and the programming algorithm can be completely simulated according to the described process.
* Program description and comment
# Include <stdio. h>
Void print (INT s []);
Int judge (int c []);
Int J = 0;
Int main ()
{
Static int sweet [10] = {,};/* initialize array data */
Int I, T [10], L;
Printf ("child/N ");
Printf ("Round 1 2 3 4 5 6 7 8 9 10/N ");
Printf ("............................. /N ");
Print (sweet);/* Number of sugar blocks in each hand */
While (Judge (sweet)/* continue the loop if the requirements are not met */
{
For (I = 0; I <10; I ++)/* divide sugar in each hand into half */
If (sweet [I] % 2 = 0)/* if it is an even number, it is split into half */
T [I] = sweet [I] = sweet [I]/2;
Else/* if it is an odd number, add 1 and then split it into half */
T [I] = sweet [I] = (sweet [I] + 1)/2;
For (L = 0; L <9; L ++)/* give the half of the sugar to the child on the right (back) side */
Sweet [L + 1] = sweet [L + 1] + T [l];
Sweet [0] + = T [9];
Print (sweet);/* output the current amount of sugar in each child's hand */
}
}
Int judge (int c [])
{
Int I;
For (I = 0; I <10; I ++)/* determines whether the sugar in each child's hand is the same */
If (C [0]! = C [I]) return 1;/* different return 1 */
Return 0;
}
Void print (INT s [])/* output the value of each element in the array */
{
Int K;
Printf ("% 2D", J ++ );
For (k = 0; k <10; k ++) printf ("% 4D", s [k]);
Printf ("/N ");
}
76. James buys books
James went to the bookstore with his father during his vacation. He selected six books, each of which had a unit price of 3.1, 1.7, 2, 5.3, 0.9, and 7.2 respectively. Unfortunately, James's father only paid a dozen dollars. In order to make James have a pleasant holiday, he agreed to buy a book, but asked me to send a mail order, james needs to select several books from six books so that the sum of unit prices is the closest to 10. Can you help James solve this problem?
* Problem analysis and Algorithm Design
By analyzing the question meaning, you can simplify the question to: select a number of summation from the six numbers to minimize the difference between sum and 10.
The question implies two problems: one is how to select several numbers from the six numbers, and the other is the difference between 10 and 10.
Selecting a number from the six numbers means selecting a number from the six numbers for combination. There are only two types of numbers in the combination process: select to join the sum, or select not to join the sum. In this way, you can use a six-fold loop to determine whether each number participates in the sum and perform a combination of all possible conditions.
Note that the difference between the result and the value 10 indicates the absolute value of the difference. For example, "9-10 =-1" and "11-10 = 1", but the difference between 9 and 11 is 1. If the difference between "9" and "10 is-1, it is wrong.
* Program description and comment
# Include <stdio. h>
# Include <math. h>
Int main ()
{
Int d [6], M, I, J;
Long B [63], flag;
Float C [6], Min, X;
Printf ("Please enter the prices of 6 books :");
For (I = 0; I <6; I ++) scanf ("% F", & C [I]);/* enter six floating point numbers */
For (I = 0, min =-1, D [0] = 0; d [0] <2; d [0] ++) /* create all six combinations and process them */
For (d [1] = 0; d [1] <2; d [1] ++)/* I: Number of Min combinations of Difference values */
For (d [2] = 0; d [2] <2; d [2] ++)/* min: minimum difference with 10 */
For (d [3] = 0; d [3] <2; d [3] ++)/* d []: Indicates whether to use this number in combination */
For (d [4] = 0; d [4] <2; d [4] ++)
For (d [5] = 0; d [5] <2; d [5] ++)
{
For (flag = 0, x = 0, j = 5; j> = 0; j -)
/* Flag: indicates the combination of the six numbers in the corresponding decimal bit X: corresponds to the sum of the six numbers */
{
X + = C [J] * d [J]; flag = flag * 10 + d [J];
}
X = (X-10> 0 )? X-10: 10-X);/* X: Combination and 10 difference */
If (Min <0)
{
Min = x;/* process the difference min calculated for the first time */
B [I ++] = flag;/* B []: array with the same min flag I: B [] array subscript */
}
Else if (min-x> 1. E-6)/* processing of new min */
{
Min = x; B [0] = flag; I = 1;
}
Else if (FABS (double) x-min) <1. E-6)
B [I ++] = flag;/* processing of equal min */
}
For (m = 0; m <I; m ++)/* the difference between all I and 10 is the combination of Min */
{
Printf ("10 (+-) %. 2f =", min );
For (flag = B [m], j = 0; flag> 0; j ++, flag/= 10)
If (flag % 10)/* restore the flag stored in B [] to a combination of numbers */
If (flag> 1) printf ("%. 2f +", C [J]);
Else printf ("%. 2f/N", C [J]);
}
}
* Running result
Please enter the prices of 6 books: 3.1 1.7 2.0 5.3 0.9 7.2
10 (+-) 0.10 = 2.00 + 0.90 + 7.20
10 (+-) 0.10 = 1.70 + 2.00 + 5.30 + 0.90
10 (+-) 0.10 = 3.10 + 1.70 + 5.30
* Questions
It can be seen that the algorithm that can generate all combinations by finding the six numbers in the program is not good, and the six-repeating loop is used to process the program is not concise enough. A more general and optimized algorithm can be designed to generate all combinations.
77. Interesting questions about posonva wine
Powalson, a famous French math, studied an interesting mathematical problem in the Age of table years: Someone has a bottle of beer with 12 pines and wants to pour 6 pines out of it, but he does not have a container with 6 pines, how can we divide beer into two popup containers?
* Problem analysis and Algorithm Design
Divide the empty bottles of the 8-and 5-tasting wines of the 12-tasting wines equally, which can be abstracted into an indefinite equation:
8x-5y = 6
The meaning is: from the 12-pin bottle to the 8-pin bottle inverted X times, and 5-pin bottle wine to the 12-pin bottle inverted y times, at last, there are 6 items in the remaining 12 items.
Use a, B, c to represent the bottles of 12, 8, and 5, and obtain the integer solution of the uncertainty equation. According to the meaning of the uncertainty equation, the inverted method is:
A-> B-> C->
X Y
The rules for pouring wine are as follows:
1) in the order of A-> B-> C->;
2) B can be retrieved from a after it is empty
3) C can be poured into a after being filled
According to the above rules, you can compile the program as follows:
* Program description and comment
# Include <stdio. h>
Void getti (int A, int y, int Z );
Int I;/* The final weight to be split */
Int main ()
{
Int A, Y, Z;
Printf ("input full A, empty B, c, get I:");/* a full bottle capacity Y: capacity of the first empty bottle Z: capacity of the second empty bottle */
Scanf ("% d", & A, & Y, & Z, & I );
Getti (A, y, z);/* follow the steps of a-> Y-> Z-> */
Getti (A, Z, Y);/* follow the steps of a-> Z-> Y-> */
}
Void getti (int A, int y, int Z)/* A: Full bottle capacity Y: capacity of the first empty bottle Z: capacity of the second empty bottle */
{
Int B = 0, c = 0;/* B: actual weight of the first bottle C: actual weight of the second bottle */
Printf ("A % d B % d C % d/n % 4D % 4D % 4D/N", A, Y, Z, A, B, C );
While (! = I | B! = I & C! = I)/* Full bottle! = I or both! = I */
{
If (! B)
{A-= y; B = y;}/* If the first bottle is empty, enter the full bottle in the first bottle */
Else if (C = z)
{A + = z; C = 0;}/* If the second bottle is full, pour the second bottle into the full bottle */
Else if (B> Z-C)/* if the weight of the first bottle> remaining space of the second bottle */
{B-= (Z-C); C = z;}/* fill the second bottle with the remaining parts in the first bottle */
Else {C + = B; B = 0;}/* Otherwise, add all the first bottles to the second bottle */
Printf ("% 4D % 4D % 4D/N", A, B, C );
}
}
* Questions
The above program only provides two wine separation methods, and does not find all the methods. Please design a new algorithm to find out all the wine sharding methods and find a method with the least number of Liquor pouring.
78. Evaluate the approximate value of π
Use the positive polygon approximation method to obtain the approximate value of π.
* Problem analysis and Algorithm Design
We used the method of "positive polygon Approximation" to find the π value that existed a long time ago. Our ancestors used this method to obtain the π value with an accuracy of 6th digits after the decimal point in the world.
The number of edges is doubled with the side length equal to the radius of the positive hexagonal side in the circle, and the twelve edges are formed to obtain the side length. repeat this process to obtain the approximate value of π.
Assume that the edges of the inner polygon of the unit circle are 2B and the number of edges is I. After the number of edges is doubled, the edges of the new polygon are as follows:
X = √ ── ─
2-2 * √ ── ─
1-B * B
── ─
2
Perimeter:
Y = 2 * I * x I: returns the number of edges of the positive polygon before doubling.
* Program description and comment
# Include <stdio. h>
# Include <math. h>
Int main ()
{
Double E = 0.1, B = 0.5, c, d;
Long int I;/* I: number of positive polygon edges */
For (I = 6; I * = 2)/* double the number of positive polygon edges */
{
D = 1.0-sqrt (1.0-B * B);/* calculate the side length of the inner side of the circle plus the regular polygon */
B = 0.5 * SQRT (B * B + D * D );
If (2 * I * B-I * E <1e-15) break;/* If the accuracy is 1 E-15, the computation is stopped */
E = B;/* Save the side length of the regular polygon as the basis for the next precision control */
}
Printf ("Pai = %. 15lf/N", 2 * I * B);/* output π value and number of edges of the regular polygon */
Printf ("the number of edges of required polygon: % LD/N", I );
}
* Running result
Pai = 3.141592653589794
The number of edges of required polygon: 100663296
* Questions
Calculate the approximate value of π using the method of approximation of the outer tangent positive polygon.
79. Evaluate the approximate value of π (2)
Using the random number method to obtain the approximate value of π
* Problem analysis and Algorithm Design
The idea of using the random number method to calculate the approximate value of π: in a square with a unit side length, the side length is the radius, and a vertex is the center of the circle. The power square is 1/4 circle. Randomly throw points into the square. If the point falls into the 1/4 circle, it is counted. If you repeatedly throw enough points into the square, the total number of points in the 1/4 circle is divided by the total number of points. The value is an approximate value of π 1/4.
You can directly program this method. Note: The π value obtained in this method can be accurate only when the number of statistics is large enough.
* Program description and comment
# Include <time. h>
# Include <stdlib. h>
# Include <stdio. h>
# Define n 30000
Int main ()
{
Float X, Y;
Int C = 0, D = 0;
Randomize ();
While (C ++ <= N)
{
X = random (101);/* X: coordinates. Generate a total of 100 random numbers between 0 and 101 */
Y = random (101);/* Y: coordinates. Generate a total of 100 random numbers between 0 and 101 */
If (x * x + y * Y <= 10000)/* determine whether a point falls in the circle using the square field */
D ++;
}
Printf ("Pi = % F/N", 4. * D/n);/* output the obtained π value */
}
* Running result
If you run the program multiple times, you may get multiple different counterparts. This is because the approximate value obtained by the statistical law is used. Only when the number of statistics is large enough can you approximate the π value. Run the command four times. The possible result is:
3.122267
3.139733
3.133733
80. An interesting property of an odd square
Programming Verification "the square of an odd number greater than 1000 is a multiple of 8 from 1 ".
* Problem analysis and Algorithm Design
This is a mathematical theorem that can be easily proved. We can write programs to verify it.
The processing process given in the question is clear and algorithms do not need to be specially designed. Verification can be performed directly according to the description of the question (only 3000 is verified in the program ).
* Program description and comment
# Include <stdio. h>
Int main ()
{
Long int;
For (A = 1001; A <= 3000; A + = 2)
{
Printf ("% ld:", a);/* output odd number itself */
Printf ("(% LD * % ld-1)/8", a, a);/* output (odd square minus 1)/8 */
Printf ("= % lD", (A * A-1)/8);/* vendor after the output is divided by 8 */
Printf ("+ % LD/N", (A * A-1) % 8);/* output the remainder after 8 Division */
}
}