1. (C組T1 3')猜年齡
美國數學家維納(N.Wiener)智力早熟,11歲就上了大學。他曾在1935~1936年應邀來中國清華大學講學。 一次,他參加某個重要會議,年輕的臉孔引人注目。于是有人詢問他的年齡,他回答說: “我年齡的立方是個4位數。我年齡的4次方是個6位數。這10個數字正好包含了從0到9這10個數字,每個都恰好出現1次。” 請你推算一下,他當時到底有多年輕。 通過瀏覽器,直接提交他那時的年齡數字。 注意:不要提交解答過程,或其它的說明文字。
【分析】循環+枚舉
源代碼:
#include <stdio.h>#include <math.h>int main(){ int age; int pow3,pow4; for(age=10;age<=30;age++) { pow3=pow(age,3); pow4=pow(age,4); PRintf("age=%d pow3=%d pow4=%d/n",age,pow3,pow4); } return 0;}程序截圖:
【答案】18
※2. (C組T3 8’)振興中華
小明參加了學校的趣味運動會,其中的一個項目是:跳格子。 地上畫著一些格子,每個格子里寫一個字,如下所示:(也可參見p1.jpg)從我做起振我做起振興做起振興中起振興中華 比賽時,先站在左上角的寫著“從”字的格子里,可以橫向或縱向跳到相鄰的格子里,但不能跳到對角的格子或其它位置。一直要跳到“華”字結束。 要求跳過的路線剛好構成“從我做起振興中華”這句話。 請你幫助小明算一算他一共有多少種可能的跳躍路線呢?答案是一個整數,請通過瀏覽器直接提交該數字。注意:不要提交解答過程,或其它輔助說明類的內容。
【分析】
法一:筆算、數路線
法二:二維數組+遞歸的綜合應用(思想很重要!)
首先把“從我做起,振興中華”這八個字按照0~7的順序編好,然后把這個方格存放在一個4*5的二維數組array里面,同時,設定一個同樣大小的flag數組來存放行走軌跡,最后還要設定一個road_flag[7]的數組來記錄行走的步子是橫向還是縱向。 接下來就是利用遞歸遍歷這個二維數組, 遞歸過程是:從0,0開始,橫著或者豎著前進,向前前進一格的條件就是沒有超出范圍,并且下一格的數字比這一格大1。每次前進一格后,就把flag數組中相應的位置標記為1,同時根據行走的步子的方向來對road_flag中的相應步數進行標記。(這里只需考慮向右走和向下走兩種情況) 如果到達了華這個字(相應的數字為7),那么就到了遞歸出口,判斷這一條路徑是否符合要求,是否能夠輸出,然后返回?! 『瘮捣祷刂螅严鄳穆窂綐擞浐筒阶訕擞浨宄?。 就這樣一直遍歷,直到把所有的路徑都找出來!
參考源代碼:
#include <stdio.h>#include <string.h>#define ROW 4#define COL 5int count; //統計路徑的次數int flag[ROW][COL]; //路徑標記int road_flag[ROW+COL-1]; //步子標記 1-向右走,2-向下走 int road_count; //記錄方案總數(走的步數) int road(int arr[][COL],int row,int col){ flag[row][col]=1; //標記路徑--每次前進一格后,就把flag數組中相應的位置標記為1 if(arr[row][col]==7) //到達"華"這個字的位置 { count++; printf("No.%d:/n",count); //判斷這一條路徑是否符合我們的要求 //if(1==road_flag[0] && 2==road_flag[1] && 2==road_flag[2] && 2==road_flag[3] && 1==road_flag[4] && 1==road_flag[5] && 1==road_flag[6]) //{ for(int rloop=0;rloop<ROW;rloop++) { for(int cloop=0;cloop<COL;cloop++) if(1 == flag[rloop][cloop]) //被標記的點,說明該點在行走路線上 printf(" # "); else printf(" ^ "); printf("/n"); } //} return 0; } //橫向走 if(col+1<COL && arr[row][col+1]==arr[row][col]+1) //列號+1不超邊界,且下一位置對應的數=上一位置對應的數+1 { road_flag[road_count] = 1; //說明可以橫向走,并用1標記原來所在的位置 road_count++; road(arr,row,col+1); //遞歸進行上述過程 //取消路徑和步子標記(此過程也是遞歸進行的) flag[row][col+1] = 0; road_count--; road_flag[road_count] = 0; } //縱向走 if(row+1<ROW && arr[row+1][col]==arr[row][col]+1) //行號+1不超邊界,且下一位置對應的數=上一位置對應的數+1 { road_flag[road_count] = 2; //說明可以橫向走,并用2標記原來所在的位置 road_count++; road(arr,row+1,col); //遞歸進行上述過程 //取消路徑和步子標記(此過程也是遞歸進行的) flag[row+1][col] = 0; road_count--; road_flag[road_count] = 0; }}int main() //"從我做起振興中華"8個字依次對應數字0~7 { int array[ROW][COL]={ {0,1,2,3,4}, {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} }; road(array,0,0); //從起點開始,遞歸遍歷 printf("count = %d/n",count); return 0;}程序截圖:
【答案】35
※3. (C組T4 13’)幻方填空
幻方是把一些數字填寫在方陣中,使得行、列、兩條對角線的數字之和都相等。 歐洲最著名的幻方是德國數學家、畫家迪勒創作的版畫《憂郁》中給出的一個4階幻方。 他把1,2,3,...16 這16個數字填寫在4 x 4的方格中。 如圖p1.jpg所示,即:16 ? ? 13? ? 11 ?9 ? ? *? 15 ? 1 表中有些數字已經顯露出來,還有些用?和*代替。 請你計算出? 和 * 所代表的數字。并把 * 所代表的數字作為本題答案提交。答案是一個整數,請通過瀏覽器直接提交該數字。注意:不要提交解答過程,或其它輔助說明類的內容。
【分析】
對比題型:打印n階魔方陣(n為奇數)
4. (C組T5 5’)公約數公倍數
我們經常會用到求兩個整數的最大公約數和最小公倍數的功能。 下面的程序給出了一種算法。 函數 myfunc 接受兩個正整數a,b 經過運算后打印出 它們的最大公約數和最小公倍數。 此時,調用 myfunc(15,20) 將會輸出:560 // 交換數值void swap(int *a,int *b){ int temp; temp=*a; *a=*b; *b=temp;}void myfunc(int a, int b){ int m,n,r; if(a<b) swap(&a,&b); m=a;n=b;r=a%b; while(r!=0) { a=b;b=r; r=a%b; } printf("%d/n",b); // 最大公約數 printf("%d/n", ____________________________________); // 最小公倍數 }
請分析代碼邏輯,并推測劃線處的代碼,通過網頁提交。注意:僅把缺少的代碼作為答案,千萬不要填寫多余的代碼、符號或說明文字?。?/p>
【分析】輾轉相除法
填空后代碼:
#include <stdio.h>// 交換數值void swap(int *a,int *b){ int temp; temp=*a; *a=*b; *b=temp;}void myfunc(int a, int b){ int m,n,r; if(a<b) swap(&a,&b); m=a; n=b; r=a%b; while(r!=0) { a=b; b=r; r=a%b; } printf("%d/n",b); // 最大公約數 printf("%d/n", m*n/b); // 最小公倍數 填空位置 }int main(){ int a,b; while(scanf("%d %d",&a,&b)!=EOF) myfunc(a,b); return 0;}程序截圖:
【答案】m*n/b
5. (A組T2 6’)排它平方數 小明正看著 203879 這個數字發呆。 原來,203879 * 203879 = 41566646641 這有什么神奇呢?仔細觀察,203879 是個6位數,并且它的每個數位上的數字都是不同的,并且它平方后的所有數位上都不出現組成它自身的數字。 具有這樣特點的6位數還有一個,請你找出它! 再歸納一下篩選要求: 1. 6位正整數 2. 每個數位上的數字不同 3. 其平方數的每個數位不含原數字的任何組成數位答案是一個6位的正整數。請通過瀏覽器提交答案。注意:只提交另一6位數,題中已經給出的這個不要提交。注意:不要書寫其它的內容(比如:說明性的文字)。
【分析】循環+數位分離+重復判斷。特別注意平方數的數據類型要設置為long long int型避免溢出問題。
源代碼:
#include <stdio.h>long long int Judge(long long int a[],long long int n) //判斷數a的各位數是否有重復 { long long int i,j; long long int flag=1; for(i=0;i<n;i++) { for(j=i+1;j<n;j++) { if(a[i]==a[j]) { flag=0; break; } } } return flag;}long long int Judge(long long int a[],int m,long long int b[],int n) //判斷數a與數b的各位數是否有重復 { long long int i,j; long long int flag=1; for(i=0;i<m;i++) { for(j=0;j<n;j++) { if(a[i]==b[j]) { flag=0; break; } } } return flag;}int main(){ long long int i,j,k; long long int num1[20],num2[20]; long long int t,tt,pownum; for(i=100000;i<999999;i++) { pownum=i*i; t=i,tt=pownum; j=0; while(t) { num1[j++]=t%10; t/=10; } if(Judge(num1,j)) { k=0; while(tt) { num2[k++]=tt%10; tt/=10; } if(Judge(num1,j,num2,k)) printf("%lld*%lld=%lld/n",i,i,pownum); } } return 0;} 程序截圖:
【答案】639172
6. (A組T4 13')顛倒的價牌
小李的店里專賣其它店中下架的樣品電視機,可稱為:樣品電視專賣店。 其標價都是4位數字(即千元不等)。 小李為了標價清晰、方便,使用了預制的類似數碼管的標價簽,只要用顏色筆涂數字就可以了(參見p1.jpg)。 這種價牌有個特點,對一些數字,倒過來看也是合理的數字。如:1 2 5 6 8 9 0 都可以。這樣一來,如果牌子掛倒了,有可能完全變成了另一個價格,比如:1958 倒著掛就是:8561,差了幾千元啊!! 當然,多數情況不能倒讀,比如,1110 就不能倒過來,因為0不能作為開始數字。 有一天,悲劇終于發生了。某個店員不小心把店里的某兩個價格牌給掛倒了。并且這兩個價格牌的電視機都賣出去了! 慶幸的是價格出入不大,其中一個價牌賠了2百多,另一個價牌卻賺了8百多,綜合起來,反而多賺了558元。 請根據這些信息計算:賠錢的那個價牌正確的價格應該是多少?答案是一個4位的整數,請通過瀏覽器直接提交該數字。注意:不要提交解答過程,或其它輔助說明類的內容。
【分析】
源代碼:
#include <stdio.h>int main(){ int i,j,p1,p2,t; int p,a[4]; int reversep1,reversep2; //int a[7]={1,2,5,6,8,9,0}; //int reverse[7]={1,2,5,9,8,6,0}; for(p1=1000;p1<=9999;p1++) { i=0; t=p1; while(t) { a[i++]=t%10; t/=10; } for(p=0;p<4;p++) { if(a[p]==6) a[p]=9; else if(a[p]==9) a[p]=6; } reversep1=1000*a[0]+100*a[1]+10*a[2]+a[3]; for(p2=1000;p2<=9999;p2++) { j=0; t=p2; while(t) { a[j++]=t%10; t/=10; } for(p=0;p<4;p++) { if(a[p]==6) a[p]=9; else if(a[p]==9) a[p]=6; } reversep2=1000*a[0]+100*a[1]+10*a[2]+a[3]; // printf("%d %d %d %d/n",p1,reversep1,p2,reversep2); if((reversep1-p1>-300 && reversep1-p1<-200) && (reversep2-p2>800 && reversep2-p2<900) && (reversep1+reversep2-p1-p2==558)) printf("%d %d %d %d/n",p1,reversep1,p2,reversep2); } } return 0;} 程序截圖:
【答案】9088
7. (A組T6 10')逆波蘭表達式 正常的表達式稱為中綴表達式,運算符在中間,主要是給人閱讀的,機器求解并不方便。 例如:3 + 5 * (2 + 6) - 1 而且,常常需要用括號來改變運算次序。 相反,如果使用逆波蘭表達式(前綴表達式)表示,上面的算式則表示為: - + 3 * 5 + 2 6 1 不再需要括號,機器可以用遞歸的方法很方便地求解。 為了簡便,我們假設: 1. 只有 + - * 三種運算符 2. 每個運算數都是一個小于10的非負整數 下面的程序對一個逆波蘭表示串進行求值。 其返回值為一個結構:其中第一元素表示求值結果,第二個元素表示它已解析的字符數。struct EV{int result; //計算結果 int n; //消耗掉的字符數 };struct EV evaluate(char* x){struct EV ev = {0,0};struct EV v1;struct EV v2;if(*x==0) return ev;if(x[0]>='0' && x[0]<='9'){ev.result = x[0]-'0';ev.n = 1;return ev;}v1 = evaluate(x+1);v2 = _____________________________; //填空位置if(x[0]=='+') ev.result = v1.result + v2.result;if(x[0]=='*') ev.result = v1.result * v2.result;if(x[0]=='-') ev.result = v1.result - v2.result;ev.n = 1+v1.n+v2.n;return ev;}請分析代碼邏輯,并推測劃線處的代碼,通過網頁提交。注意:僅把缺少的代碼作為答案,千萬不要填寫多余的代碼、符號或說明文字??!
【分析】前中后綴表達式的求值(結合數據結構棧的內容)
填空后代碼:
#include <stdio.h>#define maxlen 105struct EV{ int result; //計算結果 int n; //消耗掉的字符數 };struct EV evaluate(char* x){ struct EV ev = {0,0}; struct EV v1; struct EV v2; if(*x==0) return ev; if(x[0]>='0' && x[0]<='9') { ev.result = x[0]-'0'; ev.n = 1; return ev; } v1 = evaluate(x+1); v2 = evaluate(x+v1.n+1); //填空位置 if(x[0]=='+') ev.result = v1.result + v2.result; if(x[0]=='*') ev.result = v1.result * v2.result; if(x[0]=='-') ev.result = v1.result - v2.result; ev.n = 1+v1.n+v2.n; return ev;}int main(){ EV v=evaluate("-+3*5+261"); printf("%d/n",v.result); return 0;}程序截圖:
【答案】42
新聞熱點
疑難解答
圖片精選