2016屆藍橋杯 Java C組 省賽試題及答案
題目1:
小明很喜歡猜謎語。
最近,他被邀請參加了X星球的猜謎活動。
每位選手開始的時候都被髮給777個電子幣。
規則是:猜對了,手裡的電子幣數目翻倍,
猜錯了,扣除555個電子幣, 扣完為止。
小明一共猜了15條謎語。
戰果為:vxvxvxvxvxvxvvx
其中v表示猜對了,x表示猜錯了。
請你計算一下,小明最後手裡的電子幣數目是多少。
請填寫表示最後電子幣數目的數字。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
程式碼實現:
package 藍橋2016; public class T1 { public static void main(String[] args) { String string = "vxvxvxvxvxvxvvx"; int sum = 777; for(int i=0;i<15;i++) { if(string.charAt(i)=='v') { sum=sum*2; } else { sum=sum-555; } } System.out.println(sum); } //58497 }
題目2:
有一堆煤球,堆成三角稜錐形。具體:
第一層放1個,
第二層3個(排列成三角形),
第三層6個(排列成三角形),
第四層10個(排列成三角形),
…
如果一共有100層,共有多少個煤球?
請填表示煤球總數目的數字。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
程式碼實現:
package 藍橋2016; /*找規律: * 1 = 0+1 * 3 = 1+2 * 6 = 3+3 * 10 =6+4 * 發現:每層的數量 = 上一層的數量+以1,2,3,4以此增加的數字*/ public class T2 { public static void main(String[] args) { int rowNum = 0;//每層的數量 int sum = 0;//全部總數量 for(int i=1;i<=100;i++) {//以1,2,3,4以此增加的數字 定義為步長,步長又與i同 rowNum = rowNum + i; sum+=rowNum; } System.out.println(sum); } //171700 }
題目3:
如果把一個正整數的每一位都平方後再求和,得到一個新的正整數。
對新產生的正整數再做同樣的處理。
如此一來,你會發現,不管開始取的是什麼數字,
最終如果不是落入1,就是落入同一個迴圈圈。
請寫出這個迴圈圈中最大的那個數字。
請填寫該最大數字。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
程式碼實現:
package 藍橋2016; import java.util.Scanner; /*fenxi : * 正整數的遍歷的數字範圍?? 也不知道它有多少位?? 將每一位取出?? 對新產生的正整數再做同樣的處理?? * 1. 先實現:把一個正整數的每一位取出都平方後再求和,得到一個新的正整數(前提:不知道位數) * 例如:1234 * 1234%10 = 4 就取出來4 再1234/10 = 123 * 123 %10 =3 就取出來3 再123/10 = 12 * 依次將每一位取出來 * sum = 16+9+4+1 = 30 * 2. 需要對新產生的正整數sum再做同樣的處理。至於多少次也未知? * 需要將一次的過程放到迴圈中去; * sum應該作為下一次迴圈的num */ public class T3 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int num = scanner.nextInt();//輸入一個正整數 for(int i=0;i<100;i++) { int sum = 0;//每位數字的平方和 while(true) {//因為不知道它有多少位,就不知道需要取出位數多少次? int ge = num%10;//取出個位數 sum = sum + ge*ge;//個位數的平方累加到和中 num = num/10; //何時退出死迴圈?就是所有位數取完了? if(num == 0) {//就證明num此時已經是左邊第一位 num = sum;//sum應該作為下一次迴圈的num break; } } System.out.println(sum); } /*只展示部分結果: * 1234 30 9 81 65 61 37 58 89 145 42 20 4 16 37 58 89 145 42 20 4 16 37 58 89 145 發現 37 58 到16 這八個數形成一個迴圈圈 最大的就是145即答案*/ } }
題目4:
我們來玩一個遊戲。
同時擲出3個普通骰子(6個面上的數字分別是1~6)。
如果其中一個骰子上的數字等於另外兩個的和,你就贏了。
下面的程式計算出你能獲勝的精確概率(以既約分數表示)
仔細閱讀程式碼,填寫劃線部分缺少的內容。
public class Main
{
public static int gcd(int a, int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
public static void main(String[] args)
{
int n = 0;
for(int i=0; i<6; i++)
for(int j=0; j<6; j++)
for(int k=0; k<6; k++){
if(________________________________) n++; //填空位置
}
int m = gcd(n,6*6*6);
System.out.println(n/m + "/" + 6*6*6/m);
}
}
程式碼實現:
package 藍橋2016;
/*fenxi:
* 這題目壞的就是它的 for 迴圈的值設定的不好,它的取值只有0-5,但是骰子我們都知道是1-6所以我們判斷大小時候每個值都要加上1*/
public class T4 {
public static int gcd(int a, int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
public static void main(String[] args)
{
int n = 0;
for(int i=0; i<6; i++)
for(int j=0; j<6; j++)
for(int k=0; k<6; k++){
if(i+1==j+k+2 || j+1==i+k+2 ||k+1==i+j+2) n++; //填空位置
}
int m = gcd(n,6*6*6);
System.out.println(n/m + "/" + 6*6*6/m);
}
// 5/24
}
題目6:
B DEF
A + --- + ------- = 10
C GHI
這個算式中A到I 代表1到9的數字,不同的字母代表不同的數字。
比如:
6+8/3+952/714 就是一種解法,9
5+3/1+972/486 是另一種解法。10
這個算式一共有多少種解法?
注意:你提交應該是個整數,不要填寫任何多餘的內容或說明性文字。
方法1:迴圈巢狀 (僅需要注意分子)
package 藍橋2016;
/*fenxi:
* 給的式子說明:用1到9而且數字不重複使用 實現算式等於10
**/
public class T6 {
public static void main(String[] args) {
int count = 0;
for (int a = 1; a <= 9; a++) {
for (int b = 1; b <= 9; b++) {
if (b == a)
continue;
for (int c = 1; c <= 9; c++) {
if (c == a || c == b)
continue;
for (int d = 1; d <= 9; d++) {
if (d == a || d == b || d == c)
continue;
for (int e = 1; e <= 9; e++) {
if (e == a || e == b || e == c || e == d)
continue;
for (int f = 1; f <= 9; f++) {
if (f == a || f == b || f == c || f == d || f == e)
continue;
for (int g = 1; g <= 9; g++) {
if (g == a || g == b || g == c || g == d || g == e || g == f)
continue;
for (int h = 1; h <= 9; h++) {
if (h == a || h == b || h == c || h == d || h == e || h == f || h == g)
continue;
for (int i = 1; i <= 9; i++) {
if (i == a || i == b || i == c || i == d || i == e || i == f || i == g
|| i == h)
continue;
if (a + b*1.0 / c + (d * 100 + e * 10 + f)*1.0 / (g * 100 + h * 10 + i) == 10) {
count++;//注意此處,分子乘以1.0 保證相除時不丟棄小數
}
}
}
}
}
}
}
}
}
}
System.out.println(count);
//29
}
}
方法2:全排列(推薦此模板)
package 藍橋2016;
/*fenxi:
* 給的式子說明:用1到9而且數字不重複使用 實現算式等於10??
*
* 看成1到9的全排列:得到所有排列情況,然後將每一種情況再進行帶入算式檢測
* //實現從m個數字裡面取m個數字進行全排列(此時,m個數字不重複)
* 特別:分子要乘以1.0 否則兩個整數相除只保留整數, 應該保留小數
* */
public class T6 {
static int count =0;
public static void main(String[] args) {
int[] arr = {1, 2, 3,4,5,6,7,8,9};
sort(arr, 0, arr.length - 1);
System.out.println(count);
}
//29
/**
* @param arr 儲存要全排列的所有數字集合
* @param start 排序交換時定住的首位下標
* @param end 排序交換時末尾元素的下標
*/
public static void sort(int[] arr, int start, int end) {
// 出口
if (start == end) {// 全排列的某一種方案
if(arr[0]+arr[1]*1.0/arr[2]+(arr[3]*100+arr[4]*10+arr[5])*1.0/(arr[6]*100+arr[7]*10+arr[8])==10) {
count++;
}
return;
}
for (int i = start; i <= end; i++) {
swap(arr, start, i);
sort(arr, start + 1, end);
swap(arr, start, i);//還原
}
}
// 交換陣列元素
public static void swap(int[] arr, int i, int j) {
int c = arr[i];
arr[i] = arr[j];
arr[j] = c;
}
}
題目7:
小明最近喜歡搭數字積木,
一共有10塊積木,每個積木上有一個數字,0~9。
搭積木規則:
每個積木放到其它兩個積木的上面,並且一定比下面的兩個積木數字小。
最後搭成4層的金字塔形,必須用完所有的積木。
下面是兩種合格的搭法:
0
1 2
3 4 5
6 7 8 9
0
3 1
7 5 2
9 8 6 4
請你計算這樣的搭法一共有多少種?
請填表示總數目的數字。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
程式碼實現:
package 藍橋2016;
/*和上一個題相似的思路:先進行0到9 的全排列,然後將每一種情況再進行檢測:
*
* 將十個數字分成四層:假設是abcdefghik a在最上層(稱為第一層),b c在第二層,def在第三層,ghik在第四層
* 條件判斷:(每個積木放到其它兩個積木的上面,並且一定比下面的兩個積木數字小)
* a<b a<c
* b<d b<e c<e c<f
* d<g d<h e<h e<i f<i f<j
* */
public class T7 {
static int count =0;
public static void main(String[] args) {
int[] arr = {0,1, 2, 3,4,5,6,7,8,9};
sort(arr, 0, arr.length - 1);
System.out.println(count);
}
//768
/**
* @param arr 儲存要全排列的所有數字集合
* @param start 排序交換時定住的首位下標
* @param end 排序交換時末尾元素的下標
*/
public static void sort(int[] arr, int start, int end) {
// 出口
if (start == end) {// 全排列的某一種方案
int a = arr[0];
int b = arr[1];
int c = arr[2];
int d = arr[3];
int e = arr[4];
int f = arr[5];
int g = arr[6];
int h = arr[7];
int i = arr[8];
int j = arr[9];
if(a<b&&a<c&&b<d&&b<e&&c<e&&c<f&&d<g&&d<h&&e<h&&e<i&&f<i&&f<j) {
count++;
}
return;
}
for (int i = start; i <= end; i++) {
swap(arr, start, i);
sort(arr, start + 1, end);
swap(arr, start, i);//還原
}
}
// 交換陣列元素
public static void swap(int[] arr, int i, int j) {
int c = arr[i];
arr[i] = arr[j];
arr[j] = c;
}
}
題目8:
任意給定一個正整數N
如果是偶數,執行: N / 2
如果是奇數,執行: N * 3 + 1
生成的新的數字再執行同樣的動作,迴圈往復。
通過觀察發現,這個數字會一會兒上升到很高,
一會兒又降落下來。
就這樣起起落落的,但最終必會落到“1”
這有點像小冰雹粒子在冰雹雲中翻滾增長的樣子。
比如N=9
9,28,14,7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1
可以看到,N=9的時候,這個“小冰雹”最高衝到了52這個高度。
輸入格式:
一個正整數N(N<1000000)
輸出格式:
一個正整數,表示 不大於N的數字 ,經過冰雹數變換過程中,最高衝到了多少。
例如,輸入:
10
程式應該輸出:
52
再例如,輸入:
100
程式應該輸出:
9232
程式碼實現:
package 藍橋2016;
import java.util.Scanner;
/*fenxi:
若直接寫一個死迴圈,在其中去判斷是奇數還是偶數,將每次的到的n與max比較,比max大,就更新max;然後死迴圈出口就是n==1
輸入10 輸出16
按照以上思路: 10 5 16 8 4 2 1 那最大就是16 但是樣例中卻是52???
*有坑!!!!!!
*題目:輸入一個正整數N, 輸出:一個正整數,表示 “不大於N的數字”經過冰雹數變換過程中,最高衝到了多少
*以n=10說明:我們需要一次求出1到10 這10個數字,每個數字所對應的最大值,然後在10個最大值中找到一個最終最大值
*/
public class T8 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long n = scanner.nextLong();
long maxLast = n;
for (int i = 1; i <= n; i++) {
long max = getMax(i);
if (maxLast < max) {
maxLast = max;
}
}
System.out.println(maxLast);
}
// 獲取每個數字迴圈後得到的最大值
public static long getMax(long n) {
long max = n;
while (true) {
if (max < n)
max = n;
if (n == 1) {// 退出死迴圈
break;
}
if (n % 2 == 0) {
n = n / 2;
} else {
n = n * 3 + 1;
}
}
return max;
}
}
題目9:
四平方和定理,又稱為拉格朗日定理:
每個正整數都可以表示為至多4個正整數的平方和。
如果把0包括進去,就正好可以表示為4個數的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符號表示乘方的意思)
對於一個給定的正整數,可能存在多種平方和的表示法。
要求你對4個數排序:
0 <= a <= b <= c <= d
並對所有的可能表示法按 a,b,c,d 為聯合主鍵升序排列,最後輸出第一個表示法
程式輸入為一個正整數N (N<5000000)
要求輸出4個非負整數,按從小到大排序,中間用空格分開
例如,輸入:
5
則程式應該輸出:
0 0 1 2
再例如,輸入:
12
則程式應該輸出:
0 2 2 2
程式碼實現:
package 藍橋2016;
import java.util.Scanner;
/*疑問:怎麼知道某個正整數是否可以表示為4個正整數的平方和???何時需要0???此數的遍歷範圍和該去遍歷哪些數???輸出第一個表示法???
* fenxi:
* 可以將四個正整數記為a b c d
* 1. 初始值從0開始迴圈,進行四次巢狀迴圈 需要滿足:0 <= a <= b <= c <= d
* 可以使內層迴圈的起始值大於等於外層迴圈的當前值
* 2. 迴圈條件:a*a<=n; a*a+b*b<=n; a*a+b*b+c*c<=n; a*a+b*b+c*c+d*d<=n; */
public class T9 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
boolean isBreak = false;
for (int a = 0; a * a <= n; a++) {
if (isBreak == true)
break;
for (int b = a; a * a + b * b <= n; b++) {
if (isBreak == true)
break;
for (int c = b; a * a + b * b + c * c <= n; c++) {
if (isBreak == true)
break;
for (int d = c; a * a + b * b + c * c + d * d <= n; d++) {
if (isBreak == true)
break;
if (a * a + b * b + c * c + d * d == n) {
System.out.println(a + " " + b + " " + c + " " + d);
// 若此處用break;只能退出最裡層的for迴圈 所以需要用boolean的值標記一下狀態 然後在每一層裡面判斷一下是否要退出此for迴圈
isBreak = true;
}
}
}
}
}
}
}