本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
有一堆煤球,堆成三角棱锥形。具体: 第一层放 1个, 第二层 3个(排列成三角形), 第三层 6个(排列成三角形), 第四层 10个(排列成三角形), … 如果一共有 100层,共有多少个煤球?
找规律,观察到第i层煤球数目为i*(i+1)/2
171700
/** * @Description * @Author:PrinceHan * @CreateTime:2022/2/5 08:33 */ public class Main { public static void main(String[] args) { int sum = 0; for (int i = 1; i <= 100; i++) { sum += i * (i + 1) / 2; } System.out.println(sum); } }
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
某君从某年开始每年都举办一次生日 party,并且每次都要吹熄与年龄相同根数的蜡烛。
现在算起来,他一共吹熄了 236 根蜡烛。
请问,他从多少岁开始过生日 party 的?
请输出他开始过生日 party 的年龄数。
可以先初始化蜡烛数组,在数组中找一段连续的区间和使和等于236。可以维护一个窗口,当和小于236时,滑动右窗口,当和大于236时,滑动左侧窗口,等于236时,输出左窗口的值,即为所求。
26
/** * @Description * @Author:PrinceHan * @CreateTime:2022/2/5 08:39 */ public class B { public static void main(String[] args) { int sum = 0; int[] arr = new int[101]; for (int i = 1; i <= 100; i++) { arr[i] = i; } for (int i = 1, j = 1; i <= 100 && j <= 100; ) { if (sum < 236) sum += arr[j++]; if (sum == 236) { System.out.println(i); System.exit(0); } if (sum > 236) { sum -= arr[i]; i++; } } } }
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
B DEF A + --- + ------- = 10 C GHI
这个算式中 A ~ I 代表 0 ~ 9 的数字,不同的字母代表不同的数字。
比如: 6+8/3+952/7146+8/3+952/714 就是一种解法, 5+3/1+972/4865+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
本质上是一道求全排列的问题,用到了深搜,只是对数组的元素进行了一个处理。
29
/** * @Description * @Author:PrinceHan * @CreateTime:2022/2/5 08:48 */ public class C { static int[] nums = new int[10]; static boolean[] vis = new boolean[10]; static int ans; public static void main(String[] args) { dfs(1); System.out.println(ans); } public static void dfs(int step) { if (step == 10 && check(nums)) { ans++; return; } for (int i = 1; i < 10; i++) { if (!vis[i]) { nums[step] = i; vis[i] = true; dfs(step + 1); vis[i] = false; } } } public static boolean check(int[] a) { int num1 = a[3]; int num2 = a[4] * 100 + a[5] * 10 + a[6]; int num3 = a[7] * 100 + a[8] * 10 + a[9]; if (a[1] * num1 * num3 + a[2] * num3 + num2 * num1 == 10 * num1 * num3) return true; return false; } }
本题为代码补全填空题。
9名运动员参加比赛,需要分3组进行预赛。 有哪些分组的方案呢?
我们标记运动员为 A,B,C,… I。
下面的程序列出了所有的分组方法。
import java.util.*; public class Main { public static String remain(int[] a) { String s = ""; for(int i=0; i<a.length; i++){ if(a[i] == 0) s += (char)(i+'A'); } return s; } public static void f(String s, int[] a) { for(int i=0; i<a.length; i++){ if(a[i]==1) continue; a[i] = 1; for(int j=i+1; j<a.length; j++){ if(a[j]==1) continue; a[j]=1; for(int k=j+1; k<a.length; k++){ if(a[k]==1) continue; a[k]=1; System.out.println(____________________________); a[k]=0; } a[j]=0; } a[i] = 0; } } public static void main(String[] args) { int[] a = new int[9]; a[0] = 1; for(int b=1; b<a.length; b++){ a[b] = 1; for(int c=b+1; c<a.length; c++){ a[c] = 1; String s = "A" + (char)(b+'A') + (char)(c+'A'); f(s,a); a[c] = 0; } a[b] = 0; } } }
本题是一道代码填空题,有一定的做题技巧。首先代码中给的函数或者是变量一定会用到,可以通过打断点,调试程序是怎么运行的。在main()方法得到的是前三个字母,并将s通过参数传递给f()方法,这里意识到可能会拼接字符串,f()方法是为了获得中间三位的字符串,通过remain()方法得到包含剩余字母的字符串,将字符串拼接,打印输出即可。
System.out.println(s + " " + (char) (i + 'A') + (char) (j + 'A') + (char) (k + 'A') + " " + remain(a));
本题为代码补全填空题,请将题目中给出的源代码补全。
X星球要派出一个 5 人组成的观察团前往 W 星。
其中:
A 国最多可以派出 4 人。
B 国最多可以派出 2 人。
C 国最多可以派出 2 人。
…
那么最终派往 W 星的观察团会有多少种国别的不同组合呢?
下面的程序解决了这个问题。 数组 a[] 中既是每个国家可以派出的最多的名额。 程序执行结果为:
DEFFF CEFFF CDFFF CDEFF CCFFF CCEFF CCDFF CCDEF BEFFF BDFFF BDEFF BCFFF BCEFF BCDFF BCDEF .... (以下省略,总共101行)
下面的代码就是为了这个目的的,请仔细阅读源码,并填写划线部分缺少的代码。
import java.util.*; public class Main { public static void f(int[] a, int k, int n, String s) { if(k==a.length){ //考虑到了所有的国家 if(n==0) System.out.println(s);//n==0说明取到了5个人 return; } String s2 = s;//保存已经选择的组合 for(int i=0; i<=a[k]; i++){ ______________________; s2 += (char)(k+'A'); } } public static void main(String[] args) { int[] a = {4,2,2,1,1,3}; f(a,0,5,""); } }
观察f()方法,有出口,意识到可能要用到递归。观察到main()方法中f()方法传参k = 0,n = 5,递归结束条件为ka.length,n0则要让k增大,n减小,在代码填空处要完成这些操作。
for (int i = 0; i <= a[k]; i++) { f(a, k+1,n-i,s2);//k+1访问下一个国家,n-i表示从当前国家中减去选择的人数 s2 += (char) (k + 'A'); }
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
如下的 10 个格子:
+--+--+--+ | | | | +--+--+--+--+ | | | | | +--+--+--+--+ | | | | +--+--+--+
填入 0 ~ 9 的数字。要求:连续的两个数字不能相邻。 (左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
本质上是一道全排列,但要求连续的两个数字不相邻,不相邻指的是差的绝对值不等于1,判断一下即可。
1580
/** * @Description * @Author:PrinceHan * @CreateTime:2022/2/6 09:41 */ public class F { static int[] nums = new int[10]; static boolean[] vis = new boolean[10]; static int ans; public static void main(String[] args) { dfs(0); System.out.println(ans); } public static void dfs(int step) { if (step == 10 && check(nums)) { ans++; return; } for (int i = 0; i < 10; i++) { if (!vis[i]) { nums[step] = i; vis[i] = true; dfs(step + 1); vis[i] = false; } } } public static boolean check(int[] a) { return Math.abs(a[0] - a[1]) != 1 && Math.abs(a[1] - a[2]) != 1 && Math.abs(a[3] - a[4]) != 1 && Math.abs(a[4] - a[5]) != 1 && Math.abs(a[5] - a[6]) != 1 && Math.abs(a[7] - a[8]) != 1 && Math.abs(a[8] - a[9]) != 1 && Math.abs(a[0] - a[4]) != 1 && Math.abs(a[1] - a[5]) != 1 && Math.abs(a[2] - a[6]) != 1 && Math.abs(a[3] - a[7]) != 1 && Math.abs(a[4] - a[8]) != 1 && Math.abs(a[5] - a[9]) != 1 && Math.abs(a[0] - a[3]) != 1 && Math.abs(a[1] - a[4]) != 1 && Math.abs(a[2] - a[5]) != 1 && Math.abs(a[0] - a[5]) != 1 && Math.abs(a[1] - a[6]) != 1 && Math.abs(a[3] - a[8]) != 1 && Math.abs(a[4] - a[9]) != 1 && Math.abs(a[4] - a[7]) != 1 && Math.abs(a[5] - a[8]) != 1 && Math.abs(a[6] - a[9]) != 1; } }
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下 5张来,要求必须是连着的。
(仅仅连接一个角不算相连) 比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
一开始做的时候想着用dfs搜一下,但是运行起来方案数量比正确答案少,看了看题解发现用dfs无法解决“T”型方案。借鉴了B站上的题解,剪邮票。
从12个里面选择5个,可以初始化一个数组,长度为12,中有5个1,对这个数组进行全排列,再判断选取的是否联通,判断联通问题可以用dfs处理,在进行全排列时,要考虑全排列重复的情况,进行去重,在C++中有现成的全排列函数:
#include <algorithm> bool next_permutation(iterator start,iterator end)
可以得到不重复的全排列,但在Java中没有全排列的方法,一般通过手写dfs来实现。
116
/** * @Description * @Author:PrinceHan * @CreateTime:2022/2/6 10:20 */ public class G { static int[] a = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};//邮票数组 static int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1}; static boolean[] vis = new boolean[12]; static int ans; public static void main(String[] args) { int[] path = new int[12]; f(0, path); System.out.println(ans); } static void dfs(int[][] g, int x, int y) { g[x][y] = 0;//将1的部分标记为0 for (int i = 0; i < 4; i++) { int xx = x + dx[i]; int yy = y + dy[i]; if (in(xx, yy) && g[xx][yy] == 1) { dfs(g, xx, yy); } } } static boolean check(int[] path) { //path数组可以看作是存放全排列结果的容器,下文中的path数组也是 int[][] g = new int[3][4];//g即graph,表示选择的哪一块 for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { if (path[i * 4 + j] == 1) g[i][j] = 1;//与下标对应上 else g[i][j] = 0; } } int cnt = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { if (g[i][j] == 1) { dfs(g, i, j);//如果这块是选择的一块,从这一块开始深搜 cnt++; } } } return cnt == 1;//一次深搜证明联通 } //全排列函数,path数组可以看作是存放全排列结果的容器 static void f(int k, int path[]) { if (k == 12) { if (check(path)) ans++; } for (int i = 0; i < 12; i++) { //去重,如果选取了当前的,并且当前的与前一步的结果一样,但是前一步还没有选择,跳过这一步 if (i > 0 && a[i] == a[i - 1] && !vis[i - 1]) continue; if (!vis[i]) { vis[i] = true; path[k] = a[i]; f(k + 1, path); vis[i] = false; } } } static boolean in(int x, int y) { return x >= 0 && x < 3 && y >= 0 && y < 4; } }