1. 題目標題: 猜年齡 美國數學家維納(N.Wiener)智力早熟,11歲就上了大學。他曾在1935~1936年應邀來中國清華大學講學。 一次,他參加某個重要會議,年輕的臉孔引人注目。於是有人詢問他的年齡,他回答說: “我年齡的立方是個4位數。我年齡的4次方是個6位數。這10個數字正好包含了從0到9這10個數字,每個都恰好出現1次。” 請你推算一下,他當時到底有多年輕。 通過瀏覽器,直接提交他那時的年齡數字。 注意:不要提交解答過程,或其它的說明文字。
答案:18
2. 標題: 馬虎的算式 小明是個急性子,上小學的時候經常把老師寫在黑板上的題目抄錯了。 有一次,老師出的題目是:36 x 495 = ? 他卻給抄成了:396 x 45 = ? 但結果卻很戲劇性,他的答案竟然是對的!! 因為 36 * 495 = 396 * 45 = 17820 類似這樣的巧合情況可能還有很多,比如:27 * 594 = 297 * 54 假設 a b c d e 代表1~9不同的5個數字(注意是各不相同的數字,且不含0) 能滿足形如: ab * cde = adb * ce 這樣的算式一共有多少種呢? 請你利用計算機的優勢尋找所有的可能,並回答不同算式的種類數。 滿足乘法交換律的算式計為不同的種類,所以答案肯定是個偶數。 答案直接通過瀏覽器提交。 注意:只提交一個表示最終統計種類數的數字,不要提交解答過程或其它多余的內容。
答案:142
3. 標題: 振興中華
小明參加了學校的趣味運動會,其中的一個項目是:跳格子。
地上畫着一些格子,每個格子里寫一個字,如下所示:(也可參見p1.jpg)
從我做起振
我做起振興
做起振興中
起振興中華
比賽時,先站在左上角的寫着“從”字的格子里,可以橫向或縱向跳到相鄰的格子里,但不能跳到對角的格子或其它位置。一直要跳到“華”字結束。
要求跳過的路線剛好構成“從我做起振興中華”這句話。
請你幫助小明算一算他一共有多少種可能的跳躍路線呢?
答案是一個整數,請通過瀏覽器直接提交該數字。
答案:35
4. 標題: 幻方填空 幻方是把一些數字填寫在方陣中,使得行、列、兩條對角線的數字之和都相等。 歐洲最著名的幻方是德國數學家、畫家迪勒創作的版畫《憂郁》中給出的一個4階幻方。 他把1,2,3,...16 這16個數字填寫在4 x 4的方格中。 如圖p1.jpg所示,即: 16 ? ? 13 ? ? 11 ? 9 ? ? * ? 15 ? 1 表中有些數字已經顯露出來,還有些用?和*代替。 請你計算出? 和 * 所代表的數字。並把 * 所代表的數字作為本題答案提交。 答案是一個整數,請通過瀏覽器直接提交該數字。 答案:12
5. 題目標題:公約數公倍數 我們經常會用到求兩個整數的最大公約數和最小公倍數的功能。 下面的程序給出了一種算法。 函數 myfunc 接受兩個正整數a,b 經過運算后打印出 它們的最大公約數和最小公倍數。 此時,調用 myfunc(15,20) 將會輸出: 3 60 // 交換數值 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
標題:三部排序 一般的排序有許多經典算法,如快速排序、希爾排序等。 但實際應用時,經常會或多或少有一些特殊的要求。我們沒必要套用那些經典算法,可以根據實際情況建立更好的解法。 比如,對一個整型數組中的數字進行分類排序: 使得負數都靠左端,正數都靠右端,0在中部。注意問題的特點是:負數區域和正數區域內並不要求有序。可以利用這個特點通過1次線性掃描就結束戰斗!! 以下的程序實現了該目標。 其中x指向待排序的整型數組,len是數組的長度。 void sort3p(int* x, int len) { int p = 0; int left = 0; int right = len-1; while(p<=right){ if(x[p]<0){ int t = x[left]; x[left] = x[p]; x[p] = t; left++; p++; } else if(x[p]>0){ int t = x[right]; x[right] = x[p]; x[p] = t; right--; } else{ __________________________; //填空位置 } } } 如果給定數組: 25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0 則排序后為: -3,-2,-16,-5,0,0,0,21,19,33,25,16,18,25 請分析代碼邏輯,並推測划線處的代碼,通過網頁提交 答案:p++
7. 標題:核桃的數量 小張是軟件項目經理,他帶領3個開發組。工期緊,今天都在加班呢。為鼓舞士氣,小張打算給每個組發一袋核桃(據傳言能補腦)。他的要求是: 1. 各組的核桃數量必須相同 2. 各組內必須能平分核桃(當然是不能打碎的) 3. 盡量提供滿足1,2條件的最小數量(節約鬧革命嘛) 程序從標准輸入讀入: a b c a,b,c都是正整數,表示每個組正在加班的人數,用空格分開(a,b,c<30) 程序輸出: 一個正整數,表示每袋核桃的數量。 例如: 用戶輸入: 2 4 5 程序輸出: 20 再例如: 用戶輸入: 3 1 1 程序輸出: 3
#include <stdio.h> void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } int f(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; } return m * n / b; } int main() { int a, b, c; scanf("%d %d %d", &a, &b, &c); printf("%d", f(f(a,b), f(b,c))); return 0; }
8. 題目標題:打印十字圖 小明為某機構設計了一個十字型的徽標(並非紅十字會啊),如下所示(可參見p1.jpg) $$$$$$$$$$$$$ $ $ $$$ $$$$$$$$$ $$$ $ $ $ $ $ $$$ $$$$$ $$$ $ $ $ $ $ $ $ $ $ $$$ $ $$$ $ $ $ $ $ $ $ $ $ $ $ $ $$$$$ $ $ $ $ $ $ $ $ $ $ $ $ $$$ $ $$$ $ $ $ $ $ $ $ $ $ $$$ $$$$$ $$$ $ $ $ $ $ $$$ $$$$$$$$$ $$$ $ $ $$$$$$$$$$$$$ 對方同時也需要在電腦dos窗口中以字符的形式輸出該標志,並能任意控制層數。 為了能准確比對空白的數量,程序要求對行中的空白以句點(.)代替。 輸入格式: 一個正整數 n (n<30) 表示要求打印圖形的層數 輸出: 對應包圍層數的該標志。 例如: 用戶輸入: 1 程序應該輸出: ..$$$$$.. ..$...$.. $$$.$.$$$ $...$...$ $.$$$$$.$ $...$...$ $$$.$.$$$ ..$...$.. ..$$$$$.. 再例如: 用戶輸入: 3 程序應該輸出: ..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $...$.......$...$ $.$$$.$$$$$.$$$.$ $.$...$...$...$.$ $.$.$$$.$.$$$.$.$ $.$.$...$...$.$.$ $.$.$.$$$$$.$.$.$ $.$.$...$...$.$.$ $.$.$$$.$.$$$.$.$ $.$...$...$...$.$ $.$$$.$$$$$.$$$.$ $...$.......$...$ $$$.$$$$$$$$$.$$$ ..$...........$.. ..$$$$$$$$$$$$$.. 請仔細觀察樣例,尤其要注意句點的數量和輸出位置。
#include <stdio.h> void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } int go(int i, int j, int n) { if (i > n * 2 + 3) i = n * 4 + 6 - i; if (j > n * 2 + 3) j = n * 4 + 6 - j; if (i < j) swap(&i, &j); if (i <= 2 && j <= 2) return 0; if (i % 2 == 1 && j >= i - 2) return 1; if (j % 2 == 1 && j != i - 1) return 1; return 0; } int main() { int n; scanf("%d", &n); int i, j; for (i = 1; i <= n*4+5; i++) { for (j = 1; j <= n*4+5; j++) { if (go(i, j, n)) printf("$"); else printf("."); } printf("\n"); } return 0; }
9. 標題:帶分數 100 可以表示為帶分數的形式:100 = 3 + 69258 / 714 還可以表示為:100 = 82 + 3546 / 197 注意特征:帶分數中,數字1~9分別出現且只出現一次(不包含0)。 類似這樣的帶分數,100 有 11 種表示法。 題目要求: 從標准輸入讀入一個正整數N (N<1000*1000) 程序輸出該數字用數碼1~9不重復不遺漏地組成帶分數表示的全部種數。 注意:不要求輸出每個表示,只統計有多少表示法! 例如: 用戶輸入: 100 程序輸出: 11 再例如: 用戶輸入: 105 程序輸出: 6
#include <stdio.h> #define N 9 int num[N] = {1,2,3,4,5,6,7,8,9}; int tag[3][3] = {{4,3,2},{5,3,1},{6,2,1}}; void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } int go(int i, int n) { int a, b, c; int count = 0; for (a = 0; a < 3; a++) { int r[3] = {0} , d = 0; for (b = 0; b < 3; b++) for (c = 0; c < tag[a][b]; c++) r[b] = r[b] * 10 + num[d++]; if (r[0] + r[1] / r[2] == n && r[1] % r[2] == 0) count++; if (r[0] + r[2] / r[1] == n && r[2] % r[1] == 0) count++; if (r[1] + r[0] / r[2] == n && r[0] % r[2] == 0) count++; if (r[1] + r[2] / r[0] == n && r[2] % r[0] == 0) count++; if (r[2] + r[0] / r[1] == n && r[0] % r[1] == 0) count++; if (r[2] + r[1] / r[0] == n && r[1] % r[0] == 0) count++; } while (i < N) { int k = i + 1; while (k < N) { swap(num + i, num + k); count += go(i + 1, n); swap(num + i, num + k); k++; } i++; } return count; } int main() { int n; scanf("%d", &n); printf("%d", go(0, n)); return 0; }
10. 標題:剪格子 如圖p1.jpg所示,3 x 3 的格子中填寫了一些整數。 我們沿着圖中的紅色線剪開,得到兩個部分,每個部分的數字和都是60。 本題的要求就是請你編程判定:對給定的m x n 的格子中的整數,是否可以分割為兩個部分,使得這兩個區域的數字和相等。 如果存在多種解答,請輸出包含左上角格子的那個區域包含的格子的最小數目。 如果無法分割,則輸出 0 程序輸入輸出格式要求: 程序先讀入兩個整數 m n 用空格分割 (m,n<10) 表示表格的寬度和高度 接下來是n行,每行m個正整數,用空格分開。每個整數不大於10000 程序輸出:在所有解中,包含左上角的分割區可能包含的最小的格子數目。 例如: 用戶輸入: 3 3 10 1 52 20 30 1 1 2 3 則程序輸出: 3 再例如: 用戶輸入: 4 3 1 1 1 1 1 30 80 2 1 1 1 100 則程序輸出: 10
#include <stdio.h> #define N 10 int num[N][N]; // tag是用來標志 格子有沒有加入,用顏色來表示,1為已加入,黑色, 0為沒加入,白色 // 初始化全為白色 int tag[N][N] = {0}; int m, n; int r = 100; //判斷格子(i,j)顏色是否t,一樣的話就找他周圍顏色也為t //返回找到的總數 int find(int i, int j, int t, int ntag[][N]) { int count = 0; //出界或走過 if (i < 0 || i >= n || j < 0 || j >= m || ntag[i][j] == 1) return 0; //標為已走過 ntag[i][j] = 1; //顏色不一樣,返回 if (tag[i][j] != t) return 0; count++; count += find(i - 1, j, t, ntag); count += find(i + 1, j, t, ntag); count += find(i, j - 1, t, ntag); count += find(i, j + 1, t, ntag); return count; } //判斷是否當前的tag,能不能剪成兩塊 int isbad() { int i, j, k = 0; int t = tag[0][0]; int ntag1[N][N] = {0}; int ntag2[N][N] = {0}; //找一塊連在一起的黑格子 int ge1 = find(0, 0, t, ntag1); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { if (tag[i][j] != t) { k = 1; break; } } if (k == 1) break; } if (i == n && j == m) return 0; //找連在一起的白格子 int ge2 = find(i, j, tag[i][j], ntag2); return ge1 + ge2 != m * n; //若黑+白 != 總數 說明不止兩塊,如:黑$白# /* ##$$# #$$## 這種情況就有2塊白的,1塊黑的 */ } // 判斷格子(i,j)是否出界,以及判斷格子可不可以剪成兩塊連續的格子 int bad(int i, int j) { if (i < 0 || i >= n || j < 0 || j >= m || tag[i][j] == 1) return 1; tag[i][j] = 1; //格子加入 int b = isbad(); //判斷格子可不可以剪成兩塊連續的格子 tag[i][j] = 0; //格子退出 return b; } /* * i, j 下一個要加入的格子 * k 已加入的格子數 * count 剩余總分 * 執行完,全局tag是沒有改變的 */ void go(int i, int j, int k, int count) { // 判斷格子是否可加入 if (bad(i, j) || count < num[i][j]) return; // 格子可加入,已加入格子數+1 k++; // 如果剩余總分剛好等於加入的格子的分數,那么這種情況符合要求 if (count == num[i][j]) { if (r > k) r = k; return; } // 加入格子,tag改變為1 tag[i][j] = 1; count -= num[i][j]; // 尋找周圍格子是否可加入 go(i - 1, j, k, count); // 執行完,tag是沒有改變的 go(i + 1, j, k, count); // 執行完,tag是沒有改變的 go(i, j - 1, k, count); // 執行完,tag是沒有改變的 go(i, j + 1, k, count); // 執行完,tag是沒有改變的 // 格子退出, tag恢復為0,也就是保證 執行完,tag是沒有改變的 tag[i][j] = 0; } int main() { scanf("%d %d", &m, &n); int i, j; int half = 0; for (i = 0; i < n; i++) for (j = 0; j < m; j++) { scanf("%d", &num[i][j]); // 計算總分 half += num[i][j]; } // 判斷總分是否為偶數 if (half % 2 == 0 && half >= num[0][0] * 2) { // 計算總分的一半 half /= 2; // go(int i, int j, int k, int count) // 下一個要加入的格子為 i, j: (0,0) // 已加入的格子數為0 // half 剩余總分 go(0, 0, 0, half); } if (r == 100) r = 0; printf("%d", r); return 0; }
以上是個人的答案,不知道有沒有問題,歡迎指正。。。



