Quiz 05 === # Problem A ## code ```c= #include <stdio.h> int main(){ int c, len, n; //input int sum; int printed; while(1){ scanf("%d %d", &c, &len); if(!len){ break; } sum = 0; printed = 0; for(int i=0; i<len; i++){ scanf("%d", &n); if(n<=c){ sum += n; //print if(!printed){ printf("%d ", n); printed = 1; } else if(n<0){ printf("- %d ", n*(-1)); } else{ printf("+ %d ", n); } } } if(printed){ printf("= %d\n", sum); } else{ puts("All values have been filtered out."); } } return 0; } ``` # Problem B ## description A special game of subtraction is to find the minimum times of subtraction for letting the sequence 1, 2, 3, ..., n becomes a zero sequence 0, 0, 0, ..., 0. When taking subtraction, a limit must be satisfied: the subtraction can be made on any elements of the sequence, but each time only one subtracted value can be chosen for all the elements. For example, consider the sequence: 1, 2, 3, 4 We need at least three times to let all values in the sequence become zero, e.g., 0, 2, 2, 4 (subtract 1 and 3 by 1) 0, 0, 0, 2 (subtract 2, 2, and 4 by 2) 0, 0, 0, 0 (subtract 2 by 2) Write a program to calculate the minimum times of subtraction required for an arbitrary value of input 𝑛. **input** The input starts with an integer 𝑚 indicating the number of cases. Each case contains one integer value 𝑛. **output** For each case, output the minimum times of subtraction required for obtaining the zero sequence as mentioned above. **Example** | input | output | | ----- | ------ | | 3 4 16 255 | 3 5 8 | ## explanation - 1 ![](https://i.imgur.com/HhU4zJK.png) 由上表可發現規律: 每個數字為0前,其數字皆為2^x, x>=0 ==1==: 1=2^0^,共有1個1 ==2 2==: 2=2^1^,共有2個2 ==4 4 4 4==: 4=2^2^,共有4個4 ==8 8 8 8 8 8 8 8==: 8=2^3,共有8個8 上述可整理為下: ![](https://i.imgur.com/bWiOX9T.png) 可發現count=x+1 故找出n最後的數字為2的幾次方,再將次方數加一即為所求。 亦可視為: 2^0^ + 2^1^ + 2^2^ + ... + 2^x^ >= n 找出x的最小值並加上1 ## explanation - 2: 進一步說明上方所發現的規律 以n=16為例,先將數列的數字轉為2進位 | base 10 | 1 | 2 | ... | 15 | 16 | |:-------:|:-----:|:-----:|:---:|:-----:|:-----:| | base 2 | 00001 | 00010 | ... | 01111 | 10000 | 接著,執行subtraction 每輪執行減法時,從左至右(亦可由右至左,在此以前者做說明)判斷sequence中數字的每一位數是否為1,若為1,則做減法,使得此為數減為0。 舉例: 11(base-10) = 1011(base-2) 1. 由左數來的第一位數(2^0^)為1,故將其減去2^0^ 使得此數字變為1010 2. 由左數來的第二位數(2^1^)為1,故將其減去2^1^ 使得此數字變為1000 3. 由左數來的第三位數(2^2^)為0,故不需做任何減法 4. 由左數來的第四位數(2^3^)為1,故將其減去2^3^ 使得此數字變為0000 此數列為連續正整數,每個為數皆需要被做減的動作(每個位數,數列中必有數字的此位數之值為1),故若欲將數列的每個數減為0,最少減法次數為n轉為二進位時之位數數量 亦可視為: 2^0^ + 2^1^ + 2^2^ + ... + 2^x^ >= n 找出x的最小值並加上1 ### 深入思考:為何是將數列之數字轉為2進位,非其他的? 舉例來說,如果將數列之數轉為3進位 |base 10| 1 | 2 | 3 | 4 | 5 | 6 | |:-----:|:-:|:-:|:-:|:-:|:-:|:-:| |base 3|001|002|010|011|012|020| 執行減法時,以第一位數(3^0^)做説明 若要將1、4的第一位數轉為0,須減3^0^x1; 若要將2、5的第一位數轉為0,須減3^0^x2; 需要執行兩次動作才可將數列中的每個數之最低為轉為0 且將6(base 10)轉為二進位及三進位比較: 110(base 2):最高次為2^2^,需執行2+1=3次 020(base 3):最高次為3^1^,又因每個位數有1, 2這2種非0數之可能,需執行(1+1)*2=4次 由此可知,當數列之數轉為base 2時,才能夠獲得最少執行次數。 ## code ```c= #include <stdio.h> int main(){ int m, n; // m=number of cases, n=sequence int gp, two_pow, x; scanf("%d", &m); for(int i=0; i<m; i++){ scanf("%d", &n); //finding the smallest x x = 0; gp = 0; two_pow = 1; while(gp < n){ gp += two_pow; two_pow *= 2; x++; } printf("%d\n", x); } return 0; } ``` # Problem C ## code ```c= #include <stdio.h> int main(){ int LB, UB; //lower bound | upper bound int a, b, c, d; // ax + by [d] c | d: 1=< -1=> int count; while(1){ scanf("%d %d %d %d %d %d", &LB, &UB, &a, &b, &c, &d); if(!LB && !UB && !a && !b && !c && !d){ break; } count = 0; for(int x=LB; x<=UB; x++){ for(int y=UB; y>=LB; y--){ if((d==1) && ((a*x + b*y) <= c)){ count++; } else if((d==-1) && ((a*x + b*y) >= c)){ count++; } } } printf("The square area within %d to %d satisfying ", LB, UB); if(b>=0){ printf("%dx+%dy", a, b); } else{ printf("%dx%dy", a, b); } if(d==1){ printf("<=%d is %d.\n", c, count); } else{ printf(">=%d is %d.\n", c, count); } } } ``` ###### tags: `程設一quiz`