2018年 第9届 蓝桥杯 Java B组 省赛真题详解及总结
- 藍橋杯 Java B組 省賽決賽 真題詳解及小結匯總【2013年(第4屆)~2021年(第12屆)】
- 第11屆 藍橋杯-第1、2次模擬(軟件類)真題-(2020年3月、4月)-官方講解視頻
- 說明:部分題解思路及程序代碼 源自?藍橋杯 官網視頻(Java B組歷年真題解析)
目錄
一、第幾天
二、方格計數
三、復數冪
測試——輸出到文件
解法一
解法二
四、測試次數
解法一
解法二
五、快速排序
六、遞增三元組
解法一:if(a[i] < b[j] && b[j] < c[k])?{ ans++;?}
解法二:暴力解法
七、螺旋折線
八、日志統計
九、全球變暖
十、堆的計數
小結
競賽大綱
競賽大綱A01_有n個孩子站成一圈
競賽大綱A02_信用卡號驗證
競賽大綱A03_砝碼稱重
競賽大綱A03_砝碼稱重2
競賽大綱A03_砝碼稱重3
一、第幾天
標題:第幾天
2000年的1月1日,是那一年的第1天。
那么,2000年的5月4日,是那一年的第幾天?
注意:需要提交的是一個整數,不要填寫任何多余內容。
【答案】:125
【解析】:31 + 29 + 31 + 30 + 4 == 125
二、方格計數
標題:方格計數
如圖p1.png所示,在二維平面上有無數個1x1的小方格。
p1.png我們以某個小方格的一個頂點為圓心畫一個半徑為1000的圓。
你能計算出這個圓里有多少個完整的小方格嗎??
注意:需要提交的是一個整數,不要填寫任何多余內容。
【答案】:3137548
package provincialGames_09_2018;public class A02_方格計數 {public static void main(String[] args) {// lwx解法int count = 0;for (int x = 0; x <= 1000; x++) {for (int y = 0; y <= 1000; y++) {if ((x + 1) * (x + 1) + (y + 1) * (y + 1) <= 1000 * 1000) {count++;}}}System.out.println(count * 4);// 鄭未老師 解法1int r = 0;for (int i = -1000; i <= 1000; i++) {for (int j = -1000; j <= 1000; j++) {if (i * i + j * j <= 1000 * 1000) {if (i == 0 || j == 0) // 點不能在軸上continue;r++;}}}System.out.println(r);// 鄭未老師 解法2【稍微優化一點的解法】int N = 1000;int y = N;int ans = 0;for (int x = 1; x <= N; x++) { //掃描每一行while (x * x + y * y > N * N && y > 0) {y--;}ans += y;}System.out.println(ans * 4);} }三、復數冪
標題:復數冪
設i為虛數單位。對于任意正整數n,(2+3i)^n 的實部和虛部都是整數。
求 (2+3i)^123456 等于多少? 即(2+3i)的123456次冪,這個數字很大,要求精確表示。
答案寫成 "實部±虛部i" 的形式,實部和虛部都是整數(不能用科學計數法表示),中間任何地方都不加空格,實部為正時前面不加正號。(2+3i)^2 寫成: -5+12i,
(2+3i)^5 的寫成: 122-597i
注意:需要提交的是一個很龐大的復數,不要填寫任何多余內容。
【答案】:將答案輸出到文件,文件大小為135KB,此處不再敘述。
b > 0 ? "+" : ""
2次冪:循環一次
123456次冪:123455
//x = x*a - y*b;
//y = t*b + y*a;
測試——輸出到文件
package provincialGames_09_2018_JavaB;import java.io.FileOutputStream; import java.io.PrintStream;public class A03_PrintStream { // public class Redirectoutpublic static void main(String[] args) {try {// 一次性創建PrintStream輸出流PrintStream ps = new PrintStream(new FileOutputStream("G:\\OUT.txt"));{// 將標準輸出重定向到ps輸出流System.setOut(ps);// 向標準輸出輸出一個字符串System.out.println("普通字符串");// 向標準輸出輸出一個對象 System.out.println(new Redirectout());System.out.println(new A03_PrintStream());}} catch (Exception e) {e.printStackTrace();}} } /** 運行上面的程序將看不到任何輸出---這意味著標準輸出不再輸出到屏幕, 而是輸出到OUT.txt文件System類里提供了如下三個重定向標準輸入/輸出的方法: 1.static void setErr(PrintStream err):重定向“標準”錯誤輸出流 2.static void setIn(InputStream in):重定向“標準”輸入流 3.static void setOut(PrintStream out):重定向“標準”輸出流 */解法一
package provincialGames_09_2018_JavaB;//import java.io.*; import java.io.FileOutputStream; import java.io.PrintStream; import java.math.BigInteger;public class A03_復數冪1 {public static void main(String[] args) {try {// 改變輸出流,輸出到work.txt文件PrintStream ps = new PrintStream(new FileOutputStream("G:\\work.txt"));System.setOut(ps); // 文件輸出 用System.out.println()即可將內容輸出到文件中BigInteger a = new BigInteger("2");BigInteger b = new BigInteger("3");BigInteger x = new BigInteger("2");BigInteger y = new BigInteger("3");for (int i = 0; i < 123455; i++) {BigInteger t = x;x = x.multiply(a).subtract(y.multiply(b));y = t.multiply(b).add(y.multiply(a));}System.out.println(x + "" + ((y.compareTo(BigInteger.ZERO) > 0) ? "+" : "") + y + "i");} catch (Exception e) { // 拋出異常e.printStackTrace();}} }解法二
package provincialGames_09_2018_JavaB;import java.io.File; import java.io.PrintStream; import java.math.BigInteger;public class A03_復數冪2 {public static void main(String[] args) throws Exception {BigInteger two = BigInteger.valueOf(2);BigInteger three = BigInteger.valueOf(3);BigInteger a = BigInteger.valueOf(2);BigInteger b = BigInteger.valueOf(3);BigInteger aa = null;BigInteger bb = null;for (int i = 0; i < 123455; i++) {aa = a.multiply(two).subtract(b.multiply(three)); // a*2-(b*3)bb = a.multiply(three).add(b.multiply(two));a = aa;b = bb;}System.setOut(new PrintStream(new File("D:\\out.txt")));System.out.println(aa + (bb.compareTo(BigInteger.ZERO) > 0 ? "-" : "+") + bb + "i");} }四、測試次數
標題:測試次數
x星球的居民脾氣不太好,但好在他們生氣的時候唯一的異常舉動是:摔手機。
各大廠商也就紛紛推出各種耐摔型手機。x星球的質監局規定了手機必須經過耐摔測試,并且評定出一個耐摔指數來,之后才允許上市流通。
x星球有很多高聳入云的高塔,剛好可以用來做耐摔測試。塔的每一層高度都是一樣的,與地球上稍有不同的是,他們的第一層不是地面,而是相當于我們的2樓。
如果手機從第7層扔下去沒摔壞,但第8層摔壞了,則手機耐摔指數=7。
特別地,如果手機從第1層扔下去就壞了,則耐摔指數=0。
如果到了塔的最高層第n層扔沒摔壞,則耐摔指數=n
為了減少測試次數,從每個廠家抽樣3部手機參加測試。
某次測試的塔高為1000層,如果我們總是采用最佳策略,在最壞的運氣下最多需要測試多少次才能確定手機的耐摔指數呢?
請填寫這個最多測試次數。
注意:需要填寫的是一個整數,不要填寫任何多余內容。
【答案】:19
最佳策略、最壞運氣? ? ? ? ?打表法
解法一
package provincialGames_09_2018_JavaB;public class A04_測試次數 { // 19public static void main(String[] args) {int[][] d = new int[1001][4]; // 有j個雞蛋測試i層樓需要扔幾次for (int i = 1; i <= 1000; i++) {d[i][1] = i; // 1個雞蛋扔i次可以測試i層樓}for (int i = 1; i <= 1000; i++) {int min = Integer.MAX_VALUE;for (int j = 1; j <= i; j++) {min = Math.min(min, Math.max(j, d[i - j][2] + 1));}d[i][2] = min;}for (int i = 1; i <= 1000; i++) {int min = Integer.MAX_VALUE;for (int j = 1; j <= i; j++) {min = Math.min(min, Math.max(d[j - 1][2] + 1, d[i - j][3] + 1));}d[i][3] = min;}System.out.println(d[1000][3]);} }解法二
package provincialGames_09_2018_JavaB;public class A04_測試次數2 { // 19static final int N = 1000;static int[] f1 = new int[N + 1];static int[] f2 = new int[N + 1];static int[] f3 = new int[N + 1]; // 記錄手機數為1、2、3時,對應各層的測試次數public static void main(String[] args) {// 考慮一部手機的情況for (int i = 1; i <= N; i++) {f1[i] = i;}// 考慮兩部手機的情況for (int i = 1; i <= N; i++) {int ans = Integer.MAX_VALUE;// 嘗試1~i若干種方案, 最終記錄所有方案中 次數最小的for (int j = 1; j <= i; j++) {// 在j層扔第一個手機// 1 好的 2 壞了int _max = 1 + Math.max(f2[i - j], f1[j - 1]);ans = Math.min(ans, _max);}f2[i] = ans;}// 考慮三部手機的情況for (int i = 1; i <= N; i++) {int ans = Integer.MAX_VALUE;// 嘗試1~i若干種方案, 最終記錄所有方案中 次數最小的for (int j = 1; j <= i; j++) {// 在j層扔第一個手機// 1 好的 2 壞了int _max = 1 + Math.max(f3[i - j], f2[j - 1]);ans = Math.min(ans, _max);}f3[i] = ans;}System.out.println(f3[N]);} }五、快速排序
標題:快速排序
以下代碼可以從數組a[]中找出第k小的元素。 ?
它使用了類似快速排序中的分治算法,期望時間復雜度是O(N)的。
請仔細閱讀分析源碼,填寫劃線部分缺失的內容。
import java.util.Random;
public class Main{
?? ?public static int quickSelect(int a[], int l, int r, int k) {
?? ??? ?Random rand = new Random();
?? ??? ?int p = rand.nextInt(r - l + 1) + l;
?? ??? ?int x = a[p];
?? ??? ?int tmp = a[p]; a[p] = a[r]; a[r] = tmp;
?? ??? ?int i = l, j = r;
?? ??? ?while(i < j) {
? ? ? ? ? ? ? ? ?? ?while(i < j && a[i] < x) i++;
? ? ? ? ? ? ? ? ?? ?if(i < j) {
? ? ? ? ? ? ? ? ? ? ? ? ?? ?a[j] = a[i];
? ? ? ? ? ? ? ? ? ? ? ? ?? ?j--;
? ? ? ? ? ? ? ? ?? ?}
? ? ? ? ? ? ? ? ?? ?while(i < j && a[j] > x) j--;
? ? ? ? ? ? ? ? ?? ?if(i < j) {
? ? ? ? ? ? ? ? ? ? ? ? ?? ?a[i] = a[j];
? ? ? ? ? ? ? ? ? ? ? ? ?? ?i++;
? ? ? ? ? ? ? ? ?? ?}
? ? ? ? ?? ?}
? ? ? ? ?? ?a[i] = x;
? ? ? ? ?? ?p = i;
? ? ? ? ?? ?if(i - l + 1 == k) return a[i];
? ? ? ? ?? ?if(i - l + 1 < k) return quickSelect( _________________________________ ); //填空
? ? ? ? ?? ?else return quickSelect(a, l, i - 1, k);?? ?
?? ?}
?? ?public static void main(String args[]) {
?? ??? ?int [] a = {1, 4, 2, 8, 5, 7};
?? ??? ?System.out.println(quickSelect(a, 0, 5, 4));
?? ?}
}
注意:只提交劃線部分缺少的代碼,不要抄寫任何已經存在的代碼或符號。
【答案】:a, i + 1, r, k - (i - l + 1)
package provincialGames_09_2018_JavaB;import java.util.Random;public class A05_快速排序 {public static int quickSelect(int a[], int l, int r, int k) {Random rand = new Random();int p = rand.nextInt(r - l + 1) + l; // [0, r + 1)int x = a[p];int tmp = a[p]; a[p] = a[r]; a[r] = tmp;int i = l, j = r;while (i < j) {while (i < j && a[i] < x)i++;if (i < j) {a[j] = a[i];j--;}while (i < j && a[j] > x)j--;if (i < j) {a[i] = a[j];i++;}}a[i] = x;p = i;if (i - l + 1 == k)return a[i];if (i - l + 1 < k)return quickSelect(a, i + 1, r, k - (i - l + 1)); // 填空elsereturn quickSelect(a, l, i - 1, k);}public static void main(String args[]) {int[] a = { 1, 4, 2, 8, 5, 7 };System.out.println(quickSelect(a, 0, 5, 4));} }六、遞增三元組
標題:遞增三元組
給定三個整數數組
A = [A1, A2, ... AN],?
B = [B1, B2, ... BN],?
C = [C1, C2, ... CN],
請你統計有多少個三元組(i, j, k) 滿足:
1. 1 <= i, j, k <= N ?
2. Ai < Bj < Ck ?
【輸入格式】
第一行包含一個整數N。
第二行包含N個整數A1, A2, ... AN。
第三行包含N個整數B1, B2, ... BN。
第四行包含N個整數C1, C2, ... CN。
對于30%的數據,1 <= N <= 100 ?
對于60%的數據,1 <= N <= 1000?
對于100%的數據,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000?
【輸出格式】
一個整數表示答案
【輸入樣例】
3
1 1 1
2 2 2
3 3 3
【輸出樣例】
27?
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 ?< 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
所有代碼放在同一個源文件中,調試通過后,拷貝提交該源碼。
不要使用package語句。不要使用jdk1.7及以上版本的特性。
主類的名字必須是:Main,否則按無效代碼處理。
解法一:if(a[i] < b[j] && b[j] < c[k])?{ ans++;?}
package provincialGames_09_2018_JavaB;import java.util.Arrays; import java.util.Scanner;public class A06_遞增三元組 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int a[] = new int[n];for (int i = 0; i < n; i++) {a[i] = sc.nextInt();}Arrays.parallelSort(a);int b[] = new int[n];for (int i = 0; i < n; i++) {b[i] = sc.nextInt();}Arrays.parallelSort(b);int c[] = new int[n];for (int i = 0; i < n; i++) {c[i] = sc.nextInt();}Arrays.parallelSort(c);int ans = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {for (int k = 0; k < n; k++) {if (a[i] < b[j] && b[j] < c[k])ans++;}}}System.out.println(ans);} }解法二:暴力解法
- 當我們要排序的數據集很大時,parallelSort() 可能是更好的選擇。
- 在數組較小的情況下,最好使用 sort(),因為它可以提供更好的性能。
? ? ? 暴力:?遍歷三數組 O(N^{3})
package provincialGames_09_2018_JavaB;import java.io.FileNotFoundException; import java.util.Arrays; import java.util.Scanner;public class A06_遞增三元組2 {public static void main(String[] args) throws FileNotFoundException {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int a[] = new int[n];int b[] = new int[n];int c[] = new int[n];for (int i = 0; i < n; i++) {a[i] = sc.nextInt();}for (int i = 0; i < n; i++) {b[i] = sc.nextInt();}for (int i = 0; i < n; i++) {c[i] = sc.nextInt();}Arrays.sort(a);Arrays.sort(b);Arrays.sort(c);long ans = 0;int p = 0, q = 0;for (int i = 0; i < n; i++) {while (p < n && a[p] < b[i]) {p++;}while (q < n && c[q] <= b[i]) {q++;}ans += 1L * p * (n - q);}System.out.println(ans);} }七、螺旋折線
標題:螺旋折線
如圖p1.png所示的螺旋折線經過平面上所有整點恰好一次。 ?
p1.png對于整點(X, Y),我們定義它到原點的距離dis(X, Y)是從原點到(X, Y)的螺旋折線段的長度。 ?
例如dis(0, 1)=3, dis(-2, -1)=9 ?
給出整點坐標(X, Y),你能計算出dis(X, Y)嗎?
【輸入格式】
X和Y?
對于40%的數據,-1000 <= X, Y <= 1000 ?
對于70%的數據,-100000 <= X, Y <= 100000 ?
對于100%的數據, -1000000000 <= X, Y <= 1000000000 ?
【輸出格式】
輸出dis(X, Y) ?
【輸入樣例】
0 1
【輸出樣例】
3
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 ?< 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
所有代碼放在同一個源文件中,調試通過后,拷貝提交該源碼。
不要使用package語句。不要使用jdk1.7及以上版本的特性。
主類的名字必須是:Main,否則按無效代碼處理。
dis(0, 1)=3
dis(-2, -1)=9
dis(1, 1)=4
? ?
暴力解法:超時? ? ? ? ? ? ? ? -10^9 ≤ x、y ≤ 10^9 -> 爆int? ? ? ? ? ? ? ? ? ? ? x↓y↑、x↑y↓、x↓y↑、x↑y↓
package provincialGames_09_2018_JavaB;import java.io.FileNotFoundException; import java.util.Scanner;public class A07_螺旋折線 {// 以 右下角 對角線上的點 為 參照點,測算給定的點到參照點要走的距離public static void main(String[] args) throws FileNotFoundException {Scanner sc = new Scanner(System.in);long X = sc.nextLong(), Y = sc.nextLong();long d = 0; // 距離long n = 0; // 第幾圈if (Y > 0 && Math.abs(X) <= Y) { // 點在上面的橫線上n = Y; // 等差數列有多少項? Y項d = (Y - X) + (2 * Y); // X的最大值是Y,第一、四象限的距離---2Y} else if (X > 0 && Math.abs(Y) <= X) { // 點在最右邊的橫線上n = X;d = Y + X;} else if (Y <= 0 && X >= Y - 1 && X <= -Y) { // 點在最下邊的橫線上n = -Y;d = -(-Y - X);} else if (X < 0 && Y >= X + 1 && Y <= -X) { // 點在最左邊的橫線上n = -X - 1;d = -(Y - X - 1 - 2 * X - 1);}System.out.println(sum(1L, 2 * n, 1) * 2 - d);}/*** 等差數列求和* * @param a0 首項* @param n 項數* @param d 公差* @return*/private static long sum(long a0, long n, int d) {return (2 * a0 + (n - 1) * d) * n / 2;} }八、日志統計
標題:日志統計
小明維護著一個程序員論壇?,F在他收集了一份"點贊"日志,日志共有N行。其中每一行的格式是:
ts id ?
表示在ts時刻編號id的帖子收到一個"贊"。 ?
現在小明想統計有哪些帖子曾經是"熱帖"。如果一個帖子曾在任意一個長度為D的時間段內收到不少于K個贊,小明就認為這個帖子曾是"熱帖"。 ?
具體來說,如果存在某個時刻T滿足該帖在[T, T+D)這段時間內(注意是左閉右開區間)收到不少于K個贊,該帖就曾是"熱帖"。 ?
給定日志,請你幫助小明統計出所有曾是"熱帖"的帖子編號。 ?
【輸入格式】
第一行包含三個整數N、D和K。 ?
以下N行每行一條日志,包含兩個整數ts和id。 ?
對于50%的數據,1 <= K <= N <= 1000 ?
對于100%的數據,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000 ?
【輸出格式】
按從小到大的順序輸出熱帖id。每個id一行。 ?
【輸入樣例】
7 10 2 ?
0 1 ?
0 10 ? ?
10 10 ?
10 1 ?
9 1
100 3 ?
100 3 ?
【輸出樣例】
1 ?
3 ?
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 ?< 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
所有代碼放在同一個源文件中,調試通過后,拷貝提交該源碼。
不要使用package語句。不要使用jdk1.7及以上版本的特性。
主類的名字必須是:Main,否則按無效代碼處理。
?
package provincialGames_09_2018_JavaB;import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.PrintStream; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.SortedSet; import java.util.TreeSet;public class A08_日志統計 {// 存日志數據, ts-td分別是時刻及id,組合成對象, 存儲在R中static class R { // 定義內部類int ts, td;// 時刻及id}public static void main(String[] args) throws FileNotFoundException { // System.setIn(new FileInputStream("E:\\in8.txt")); // System.setOut(new PrintStream("E:\\out8.txt"));Scanner sc = new Scanner(System.in);int N = sc.nextInt(), D = sc.nextInt(), K = sc.nextInt();R[] rs = new R[N];for (int i = 0; i < N; i++) {// 讀取日志數據R r = new R();r.ts = sc.nextInt();r.td = sc.nextInt();rs[i] = r;}// 匿名內部類 定義 排序器 自定義 比較器Arrays.sort(rs, new Comparator<R>() {// 按照時刻ts對一個記錄R做升序排序@Overridepublic int compare(R r1, R r2) {return r1.ts - r2.ts;}});// cnt: 用于給id計數 記錄id及其出現的次數Map<Integer, Integer> cnt = new HashMap<Integer, Integer>();// answers: 用于存儲答案(各個id), 因為要求答案輸出有序, 這里直接用TreeSetSortedSet<Integer> answers = new TreeSet<Integer>();// 尺取法【通常是:雙指針】int j = 0;// 移動哨兵---用于探測的指針for (int i = 0; i < N; ++i) {// i: 尺取法的起點---頭部// 循環條件: i指向的時刻-i指向的時刻 < Dwhile (j < N && rs[j].ts - rs[i].ts < D) {int td = rs[j].td;Integer exist = cnt.get(td);// 每一次循環,都要統計id,計數if (exist != null) {cnt.put(td, exist + 1);} else {cnt.put(td, 1);// id第一次出現}// 判斷id數是否 >= K【判斷是否滿足條件】id放入answers中if (cnt.get(td) >= K) {answers.add(td);}j++;}// (馬上i就要更新了)將上一個i對應的id的計數-1// 上一個區間, td的計數要扣除, 不干擾下一個區間的統計Integer cntOfI = cnt.get(rs[i].td);if (cntOfI != null) {cnt.put(rs[i].td, cntOfI - 1);}}// 輸出答案---輸出各個idfor (Integer i : answers) {System.out.println(i);}} }九、全球變暖
標題:全球變暖
你有一張某海域NxN像素的照片,"."表示海洋、"#"表示陸地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中"上下左右"四個方向上連在一起的一片陸地組成一座島嶼。例如上圖就有2座島嶼。 ?
由于全球變暖導致了海面上升,科學家預測未來幾十年,島嶼邊緣一個像素的范圍會被海水淹沒。具體來說如果一塊陸地像素與海洋相鄰(上下左右四個相鄰像素中有海洋),它就會被淹沒。 ?
例如上圖中的海域未來會變成如下樣子:
.......
.......
.......
.......
....#..
.......
.......
請你計算:依照科學家的預測,照片中有多少島嶼會被完全淹沒。 ?
【輸入格式】
第一行包含一個整數N。 ?(1 <= N <= 1000) ?
以下N行N列代表一張海域照片。 ?
照片保證第1行、第1列、第N行、第N列的像素都是海洋。 ?
【輸出格式】
一個整數表示答案。
【輸入樣例】
7?
.......
.##....
.##....
....##.
..####.
...###.
....... ?
【輸出樣例】
1 ?
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 ?< 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
所有代碼放在同一個源文件中,調試通過后,拷貝提交該源碼。
不要使用package語句。不要使用jdk1.7及以上版本的特性。
主類的名字必須是:Main,否則按無效代碼處理。
連通塊問題+計數? ? ? ? ? ? ? ?N ≤ 10^3? ? N*N?≤ 10^6
:陸地(塊)的個數;:與水相鄰的陸地數量。==》==,ans++
- 深搜dfs:遞歸深度過深,棧內存不足。
- 寬搜bfs:O(n)最多為10^6,非遞歸。
- 對象???????????+??????隊列
- Object????????+????Queue
- 自定義對象???用隊列維護???????????由一個點,向四周擴散。
十、堆的計數
標題:堆的計數
我們知道包含N個元素的堆可以看成是一棵包含N個節點的完全二叉樹。 ?
每個節點有一個權值。對于小根堆來說,父節點的權值一定小于其子節點的權值。 ?
假設N個節點的權值分別是1~N,你能求出一共有多少種不同的小根堆嗎? ?
例如對于N=4有如下3種:
? ? 1
? ?/ \
? 2 ? 3
?/
4
? ? 1
? ?/ \
? 3 ? 2
?/
4
? ? 1
? ?/ \
? 2 ? 4
?/
3
由于數量可能超過整型范圍,你只需要輸出結果除以1000000009的余數。 ?
【輸入格式】
一個整數N。 ?
對于40%的數據,1 <= N <= 1000 ?
對于70%的數據,1 <= N <= 10000 ?
對于100%的數據,1 <= N <= 100000
【輸出格式】
一個整數表示答案。 ?
【輸入樣例】
4 ?
【輸出樣例】
3
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 ?< 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
所有代碼放在同一個源文件中,調試通過后,拷貝提交該源碼。
不要使用package語句。不要使用jdk1.7及以上版本的特性。
主類的名字必須是:Main,否則按無效代碼處理。
??
package provincialGames_09_2018_JavaB;import java.util.Scanner;public class A10_堆的計數 {static final int MOD = 1000000009;public static int N;static int[] size; // 記錄每個節點的sizestatic long[] jie; // 記錄1~N的階乘static long[] ni; // 記錄1~N的階乘的逆元(關于MOD)public static void main(String[] args) {Scanner sc = new Scanner(System.in);N = sc.nextInt();size = new int[N + 1];jie = new long[N + 1];ni = new long[N + 1];initSize();initJie();System.out.println(dp());}private static long dp() {long[] d = new long[N + 1]; // d[i]表示的是i號節點作為根,小根堆的種數for (int x = N; x >= 1; x--) {if (2 * x + 1 <= N)d[x] = c(size[x] - 1, size[2 * x]) * d[2 * x] % MOD * d[2 * x + 1] % MOD;else if (2 * x <= N)d[x] = c(size[x] - 1, size[2 * x]) * d[2 * x] % MOD;elsed[x] = 1;}return d[1];}private static void initJie() {jie[0] = 1;ni[0] = 1;for (int i = 1; i <= N; i++) {jie[i] = jie[i - 1] * i % MOD;ni[i] = pow(jie[i], MOD - 2);}}/*** 快速求a的n次方* * @param a* @param n* @return*/private static long pow(long a, int n) {if (a == 0)return 0;long ans = 1;long x = a;while (n > 0) {if ((n & 1) == 1)ans = ans * x % MOD;n >>= 1;x = x * x % MOD;}return ans;}static long c(int n, int r) {return jie[n] * ni[r] % MOD * ni[n - r] % MOD;}private static void initSize() {for (int i = N; i >= 1; i--) {size[i] = (2 * i <= N ? size[2 * i] : 0) + (2 * i + 1 <= N ? size[2 * i + 1] : 0) + 1;}} }小結
dfs
競賽大綱
競賽大綱A01_有n個孩子站成一圈
【編程大題】花朵數 一個 N 位的十進制正整數,如果它的每個位上的數字的 N 次方的和等于這個數本身,?
則稱其為花朵數。 例如:當 N=3 時,153 就滿足條件,因為 1^3 + 5^3 + 3^3 = 153,
這樣的數字也被稱為 水仙花數(其中,“^”表示乘方,5^3 表示 5 的 3 次方,也就是立方)。?
當 N=4 時,1634 滿足條件,因為 1^4 + 6^4 + 3^4 + 4^4 = 1634。 當 N=5 時,92727 滿足條件。?
實際上,對 N 的每個取值,可能有多個數字滿足條件。 程序的任務是:求 N=21 時,所有滿足條件的花朵數。
注意:這個整數有 21 位,它的 各個位數字的 21 次方之和正好等于這個數本身。 如果滿足條件的數字不只有一個,
請從小到大輸出所有符合條件的數字,每個數字占一 行。因為這個數字很大,請注意解法時間上的可行性。
要求程序在 1 分鐘內運行完畢。
【程序運行參考結果】 128468643043731391252 449177399146038697307?
【Java 組代碼填空】 有 n 個孩子站成一圈,從第一個 孩子開始順時針方向報數,
報到 3 的人出列,下一個 人繼續從 1 報數,直到最后剩下一個孩子為止。
問剩下第幾個孩子。
下面的程序以 10 個孩子為例,模擬了這個 過程,請完善之。
(提示:報數的過程被與之邏輯等價的更容易操作的 過程所代替)。?
625 這個數字很特別,625 的平方等于 390625,剛好其末 3 位是 625 本身。
除了 625, 還有其它的 3 位數有這個特征嗎?還有一個!
該數是:_____________?
【參考答案】 376?
【代碼填空--java】
下面的代碼定義了一個方法 hasSameChar,用于判定一個給定的串中是否含有重復的字
符,比如“about”中,就沒有重復的字符,而“telecom”,“aabaa”中都含有重復的字符,
其中“e”重復了 2 次,而“a”重復了 4 次,這些都算作有重復。
請根據方法的說明,分析給出的源程序,并填寫劃線部分缺失的代碼。
注意,只填寫缺少的,不要重復周圍已經給出的內容,也不要填寫任何說明性文字等。
public class A
{
?? ? 判斷串 s 中是否含有重復出現的字符
?? ? 如果有重復則返回 true
?? ? 其它情況返回 false
?? ?
?? ? 判斷的思路是:從左到右掃描每個字符
?? ? 對當前的字符,從右向左在 s 串中搜索它的出現位置,可以用 lastIndexOf 方法
?? ? 如果找到的位置與當前的位置不同,則必然存在該字符的重復現象,即可返回 true
?? ? 其它情況返回 false
?? ?
?? ? 在特殊情況下,比如傳入的是空指針,或者 s 為空串,或者只含有 1 個字符,都不可能含有
?? ?重復字符,
?? ? 因此,這些情況直接返回 false
?? ?
?? ?public static boolean hasSameChar(String s){
?? ??? ?if(s==null || s.length()<2) return false;
?? ??? ?for(int i=0; i<s.length(); i++){
?? ??? ??? ?char c = s.charAt(i);
?? ??? ??? ?int k = s.lastIndexOf(c);
?? ??? ??? ?if(____________________) return true;
?? ??? ?}
?? ??? ?return false;
?? ?}
?? ?public static void main(String[] args){
?? ??? ?System.out.println(hasSameChar("a")); //false
?? ??? ?System.out.println(hasSameChar("abcdefg")); //false
?? ??? ?System.out.println(hasSameChar("abacdefag")); //true
?? ??? ?System.out.println(hasSameChar("abcdebfg")); //true
?? ?
?? ?}
}
競賽大綱A02_信用卡號驗證
【編程大題】信用卡號驗證?
當你輸入信用卡號碼的時候,有沒有擔心輸錯了而造成損失呢?
其實可以不必這么擔 心,因為并不是一個隨便的信用卡號碼都是合法的,
它必須通過 Luhn 算法來驗證通過。?
該校驗的過程:?
1、從卡號最后一位數字開始,逆向將奇數位(1、3、5 等等)相加。
2、從卡號最后一位數字開始,逆向將偶數位數字,
先乘以 2(如果乘積為兩位數,則 將其減去 9),再求和。?
3、將奇數位總和加上偶數位總和,結果應該可以被 10 整除。?
例如,卡號是:5432123456788881?
則奇數、偶數位(用紅色標出)分布:5432123456788881?
奇數位和=35?
偶數位乘以 2(有些要減去 9)的結果:1 6 2 6 1 5 7 7,求和=35。?
最后 35+35=70 可以被 10 整除,認定校驗通過。?
請編寫一個程序,從標準輸入獲得卡號,然后判斷是否校驗通過。
通過顯示:“成功”, 否則顯示“失敗”。?
比如,用戶輸入:356827027232780?
程序輸出:成功?
【程序測試參考用例】?
356406010024817 ? ? 成功?
358973017867744 ? ? 成功?
356827027232781 ? ? 失敗?
306406010024817 ? ? 失敗?
358973017867754 ? ? 失敗
競賽大綱A03_砝碼稱重
【編程大題】
用天平稱重時,我們希望用盡可能少的砝碼組合稱出盡可能多的重量。
如果只有 5 個砝碼,重量分別是 1,3,9,27,81。則它們可以組合稱出 1 到 121 之間
任意整數重量(砝碼允許放在左右兩個盤中)。
本題目要求編程實現:對用戶給定的重量,給出砝碼組合方案。
例如:
用戶輸入:
5
程序輸出:
9-3-1
用戶輸入:
19
程序輸出:
27-9+1
要求程序輸出的組合總是大數在前小數在后。
可以假設用戶的輸入的數字符合范圍 1~121。
【解題思路提示】
我們把已知的砝碼序列記為:x1, x2, x3, x4, x5, x6 (這里多加一個標準砝碼,為解題敘
述方便)
對于任意給定的重量 x,如果剛好等于 xi 則問題解決。
否則一定會位于兩個標準砝碼重量的中間,不妨設為:xi < x < xj
令 a = x – xi, b = xj – x
則,x 要么可以表示為: xi + a, 要么可以表示為: xj – b
這樣問題就歸結為怎樣表示出 a 或 b
另一思路:對于每個 xi,可以乘以一個系數 ki,再求和。
ki 的數值無外乎:-1 0 1
這樣,因為標準砝碼的數量的很少的,我們就可以多層循環暴力組合 ki 來求解。
還有更“土氣”但有效的思路:既然輸入范圍只有 120 左右,如果對每一種情況都做人
工求解,只要列一個大表,等查詢的時候,直接輸出答案就好了啊!但…這似乎是個耗時的
工程…
解題思路:可以用三進制解決,三進制上每一位都對應著一個砝碼。
但是需要注意的是題目中的每一種砝碼都只有一個。三進制中卻是會出現2的。
所以需要對三進制進行改變;大體思想為:右邊加兩個砝碼變成左邊加一個右邊加一個。
也就是說加兩個砝碼相當于加一個大的再減去一個小的。
在數字上的體現就是:將2變成-1更高位上進1。
? ? int arr[] = {1, 3, 9, 27, 81};
?? ??? ?boolean flag = true;
?? ??? ?for(int x: arr) {
?? ??? ??? ?if(n == x) {
?? ??? ??? ??? ?System.out.println(x);
?? ??? ??? ??? ?flag = false;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?if(flag) {
?? ??? ??? ?String str;
?? ??? ??? ?int temp;
?? ??? ??? ?for(int i = 0; i < arr.length-1; i++) {
?? ??? ??? ??? ?if( arr[i] < n && n < arr[i+1]) {
?? ??? ??? ??? ??? ?int a = n - arr[i];
?? ??? ??? ??? ??? ?int b = arr[i+1] - n;
?? ??? ??? ??? ??? ?str = arr[i+1] + "-" + arr[i];
?? ??? ??? ??? ??? ?temp = arr[i+1] - arr[i];
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
數字類型的toString()方法可以接收表示轉換基數(radix)的可選參數,
如果不指定此參數,轉換規則將是基于十進制。同樣,也可以將數字轉換為其他進制數(范圍在2-36)
var n = 17;
n.toString();//'17'
n.toString(2);//'10001'
n.toString(8);//'21'
n.toString(10);//'17'
n.toString(12);//'15'
n.toString(16);//'11'
競賽大綱A03_砝碼稱重2
package provincialGames_09_2018_JavaB;import java.util.Scanner; import java.util.Stack;public class 競賽大綱A03_砝碼稱重2 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int input = sc.nextInt(); // 1 - 121int[] arr = new int[] { 1, 2, 3 };int[] a, b, c, d, e;a = b = c = d = e = new int[] { -1, 0, 1 };for (int ai : a) {for (int bi : b) {for (int ci : c) {for (int di : d) {for (int ei : e) {if (input == ei * 81 + di * 27 + ci * 9 + bi * 3 + ai * 1) {System.out.println("(" + ei * 81 + ")+(" + di * 27 + ")+(" + ci * 9 + ")+(" + bi * 3 + ")+(" + ai * 1 + ")");}}}}}}} }競賽大綱A03_砝碼稱重3
package provincialGames_09_2018_JavaB;import java.util.Scanner; import java.util.Stack;public class 競賽大綱A03_砝碼稱重3 {public static void f(int n) {int[] sign = new int[] { -1, 0, 1 }; // 定義符號StringBuffer sb = new StringBuffer();for (int a : sign) {for (int b : sign) {for (int c : sign) {for (int d : sign) {for (int e : sign) {int i = a * 1;int j = b * 3;int k = c * 9;int l = d * 27;int m = e * 81;if (i + j + k + l + m == n) { // 找到結果// 如果不為0,則添加元�??,并在"正數"前添�??"+"�??sb.append(m != 0 ? (m > 0 ? "+" + m : m) : "");sb.append(l != 0 ? (l > 0 ? "+" + l : l) : "");sb.append(k != 0 ? (k > 0 ? "+" + k : k) : "");sb.append(j != 0 ? (j > 0 ? "+" + j : j) : "");sb.append(i != 0 ? (i > 0 ? "+" + i : i) : "");sb.deleteCharAt(0); // 去掉首元素的"+"�??;System.out.println(sb);return;}}}}}}}public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt(); // 輸入重量f(n);} }多謝觀看~
總結
以上是生活随笔為你收集整理的2018年 第9届 蓝桥杯 Java B组 省赛真题详解及总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2016年 第7届 蓝桥杯 Java B
- 下一篇: 2019年 第10届 蓝桥杯 Java