傳智杯第一屆 真題解析 Jaca
例題一
從古至今,各種末日謠言層出不窮。假如現在有這樣一個謠言:天文學家在2014年6月1日,發現一顆行星,根據該行星的執行軌道,在3000天以後,該行星將撞擊地球。現在,請編寫Java程式計算,該謠言指向的“世界末日”是哪一天?
要求輸出格式為:xxxx-xx-xx(例如:2015-12-12),不要新增任何其他多餘文字。
輸出描述:
計算的結果日期,格式為:xxxx-xx-xx
輸出樣例:
2015-12-12
思路
一開始我想硬算髮現有點麻煩,然後看了下大佬的題解,才曉得
還有Data類,記住了
import java.util.Calendar;
import java.util.Date;
public class Answer1 {
public static void main(String[] args) {
int year=2014;//date的輸出為1900年到現在的年數,因此需要具體年份時需要+1900
int month=6;//需要注意,在呼叫calendar或date類的方法時,輸入或輸出的月份均為0-11
int day=1;
int add=3000;
//1.呼叫calendar的add方法
Calendar calendar = Calendar.getInstance();
calendar. set(year, month-1, day);
calendar.add(Calendar.DATE, add);
System.out.println(calendar.get(Calendar.YEAR)+"-"+(calendar.get(Calendar.MONTH)+1)
+"-"+calendar.get(Calendar.DATE));
//2.直接用calendar設定增加後的日,進行輸出
Calendar calendar1 = Calendar.getInstance();
calendar1.set( year, month-1, day+add);
System.out.println(calendar.get(Calendar.YEAR)+"-"+(calendar.get(Calendar.MONTH)+1)
+"-"+calendar.get(Calendar.DATE));
//3.直接用calendar設定增加後的日,再呼叫date格式化
Date date = new Date(year, month-1, day+add);
System.out.println(date.getYear()+"-"+(date.getMonth()+1)+"-"+date.getDate());
}
}
答案:2015-12-01
例題二
由1到n的平方個數字組成的n×n階方陣(n為任意給定的一個不小於3的奇數),它的每行、每列及對角線上的數字和都相等,稱為n階魔方陣。它的每行、每列及對角線上的數字和為n×(n² + 1) / 2。該方陣的排列方法是:
(1) 將數字1放在第一行的中間位置上,即(0,n/2)位置;
(2) 下一個數放在當前位置(i, j)的上一行(i-1)、下一列(j+1),即當前位置的右上方;如果出現以下情況,則修改填充位置:
① 若當前位置是第一行,下一個數放到最後一行,即把i-1修改為n-1;
② 若當前位置是最後一列,下一個數放在第一列,即把j-1修改為n-1;
③ 若下一個數要放的位置已經有數字,則下一個數放在當前位置的下一行,相同列。
(3) 重複以上過程,直到n²個數字不重複的填入方陣中。
根據以上描述,請使用Java語言,設計一個程式,輸出n階魔方陣。
輸入描述:
一個大於等於3的奇數n,不建議太大,3-9即可
輸出描述:
一個n*n的數字矩陣,每行的數字之間採用一個製表符"\t"分隔
輸入樣例:
3
輸出樣例:
8 1 6
3 5 7
4 9 2
無腦照題目模擬一下,寫完之後看大佬寫的,發現其實
整個就是:下一個數在當前數的右上方,如果超出了正方
形範圍就取摸,如果右上方有數字已經放了,就放在當
前數的正下方
無腦模擬
package 傳智杯第一屆;
import java.util.Scanner;
public class No2 {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int n=input.nextInt();
int [][]arr=new int[n][n];
int j=(n/2);
int i=0;
for(int m=1;m<=n*n;m++){
arr[i][j]=m;
/*
下一個數放在當前位置(i, j)的上一行(i-1)、下一列(j+1),即當前位置的右上方;如果出現以下情況,則修改填充位置:
若當前位置是第一行,下一個數放到最後一行,即把i-1修改為n-1;
*/
if(i==0&&arr[n-1][(j+1+n)%n]==0){
i=n-1;
j=(j+1+n)%n;
}
//②若當前位置是最後一列,下一個數放在第一列,即把j-1修改為n-1;
else if(j==n-1&&arr[(i-1+n)%n][0]==0){
i=(i-1+n)%n;
j=0;
}
//③ 若下一個數要放的位置已經有數字,則下一個數放在當前位置的下一行,相同列。
else if(arr[(i-1+n)%n][(j+1+n)%n]!=0){
i=(i+1+n)%n;
}
else {
i=(i-1+n)%n;
j=(j+1+n)%n;
}
}
for(int m=0;m<n;m++){
for(int k=0;k<n;k++){
System.out.print(arr[m][k]+"\t");
}
System.out.println();
}
}
}
大佬簡易程式碼
import java.util.Scanner;
public class Answer2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
int num[][]=new int[n][n];
int i=0;
int j=n/2;
int k=1;
while(k<=n*n){
if (num[i][j]==0) {
num[i][j]=k++;
i=(i-1+n)%n;
j=(j+1+n)%n;
}else {
i=(i+1+n)%n;
}
}
for (i = 0; i < n; i++) {
for(j=0;j<n;j++){
System.out.print(num[i][j]+"\t");
}
System.out.println();
}
}
}
例題三
從前,某國王在處決500名死囚犯時突發奇想,想赦免其中的一個人,於是他把這500個死囚犯從1到500編號,都放到一片空地上,讓大家手牽手組成一個大環。從1號開始報數,凡是報數為3的倍數的人就要被殺掉,每輪過後,剩下的人組成一個較小的環,繼續報數(注意,上一輪最後一人報數後,下一輪的第一個人要繼續往下報,而不是重新從1開始),直到剩下最後一個人為止。請編寫程式計算,最終這個幸運的人是幾號?
輸出描述:
一個整數,表示最終活下來的人員編號
輸出樣例:
55
思路阿瑟夫環
問題
import java.util.Scanner;
public class No3{
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int n=500;
int m=3;
int res=0;
for(int i=2;i<=n;i++){
res=(res+m)%i;
}
System.out.println(res+1);
}
}
答案:436
例題四
給定一個正整數m(m最小是一個兩位數),現在想從組成m這個數的數字中,去掉其中的n個數字(0 < n < m的位數),但保持每位上的數字相對順序不變,使得剩餘的數字組成的數是最大值。例如:
當m = 51342,n = 1;則結果應該是去掉數字1,剩餘的值最大,為5342;
當m = 51342,n = 2;則結果應該是去掉數字1、3,剩餘的值最大,為542;
當m = 51342,n = 3;則結果應該是去掉數字1、3、2,剩餘的值最大,為54;
請使用Java語言程式設計,實現該演算法。其中的m和n按要求輸入正確範圍內的數字即可,無需做合法校驗。
輸入描述:
第一行輸入正整數m(m >= 10)
第二行輸入去掉的數字個數n(0 < n < m的位數)
輸出描述:
去掉n個數字後的最大值
輸入樣例:
51342
2
輸出樣例:
542
思路:
dfs 遞迴實現組合型列舉 類似於給定一個數,從中從前往後
選取n個數,湊成一個新的數,求這個數的最大值
import java.util.Scanner;
public class No4 {
static int Max=-1;
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String m=input.next();
int n=input.nextInt();
char []temp=m.toCharArray();
int nn=m.length()-n;
int []vis=new int[nn];
String []arr=new String[nn];
dfs(arr,nn,0,temp,0);
System.out.println(Max);
}
public static void dfs(String []arr,int n,int level,char []temp,int next){
if(level>=n){
String tempsum="";
for(int i=0;i<n;i++){
tempsum+=arr[i];
}
int sum=Integer.parseInt(tempsum);
if(sum>Max)
Max=sum;
return;
}
for(int i=next;i<temp.length;i++ ){
arr[level]=temp[i]+"";
dfs(arr,n,level+1,temp,i+1);
}
}
}
例題五
小智拿到一個數列{a1, a2, …, an},現在他想從這個數列中取出若干數,組成一個新的數列{ai1, ai2, …, aim},其中索引i1, i2, …, im保持遞增,也就是說數列中各個數仍然保持在原數列中的先後順序。並且在新數列中,對於任意索引ix > iy,都有aix > aiy,也就是說新數列是一個遞增的子序列。
請編寫程式,求出符合上述要求的最長遞增子序列的長度。
例如數列[1, 3, 6, 7, 9, 4, 10, 5, 6],最長遞增子序列為[1, 3, 6, 7, 9, 10],長度是6。
輸入描述:
任意個數的整數,中間使用空格分隔
輸出描述:
一個整數,表示符合題目要求的最長子序列的長度
輸入樣例:
1 3 6 7 9 4 10 5 6
輸出樣例:
6
思路
簡單的dp,最長上升子序列問題
import java.util.Scanner;
public class No5 {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String In=input.nextLine();
String arrtemp[]=In.split("\\s+");
int n=arrtemp.length;
int []arr=new int[n+1];
int []dp=new int[n+1];
for(int i=0;i<n;i++){
arr[i]=Integer.parseInt(arrtemp[i]);
}
int ans=0;
for(int i=0;i<n;i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(arr[i]>arr[j])
dp[i]=Math.max(dp[i],dp[j]+1);
}
ans=Math.max(dp[i],ans);
}
System.out.print(ans);
}
}