Skip to content

Commit e5bfd19

Browse files
committed
modify code
1 parent fb03c12 commit e5bfd19

File tree

2 files changed

+144
-8
lines changed

2 files changed

+144
-8
lines changed

src/class39/Code02_SnacksWaysMain.java renamed to src/class39/Code02_SnacksWaysMain1.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
//不要拷贝包信息的内容
1+
// 不要拷贝包信息的内容
22
package class39;
33

4-
//本文件是Code02_SnacksWays问题的牛客题目解答
5-
//但是用的分治的方法
6-
//这是牛客的测试链接:
7-
//https://www.nowcoder.com/questionTerminal/d94bb2fa461d42bcb4c0f2b94f5d4281
8-
//把如下的全部代码拷贝进编辑器(java)
9-
//可以直接通过
4+
// 课堂版本
5+
// 本文件是Code02_SnacksWays问题的牛客题目解答
6+
// 但是用的分治的方法
7+
// 这是牛客的测试链接:
8+
// https://www.nowcoder.com/questionTerminal/d94bb2fa461d42bcb4c0f2b94f5d4281
9+
// 把如下的全部代码拷贝进编辑器(java)
10+
// 可以直接通过
1011
import java.util.Map.Entry;
1112
import java.util.Scanner;
1213
import java.util.TreeMap;
1314

14-
public class Code02_SnacksWaysMain {
15+
public class Code02_SnacksWaysMain1 {
1516

1617
public static void main(String[] args) {
1718
Scanner sc = new Scanner(System.in);
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// 不要拷贝包信息的内容
2+
package class39;
3+
4+
//优化版本
5+
import java.util.Arrays;
6+
import java.util.Scanner;
7+
8+
public class Code02_SnacksWaysMain2 {
9+
10+
public static void main(String[] args) {
11+
Scanner sc = new Scanner(System.in);
12+
while (sc.hasNext()) {
13+
size = sc.nextInt();
14+
long w = (long) sc.nextInt();
15+
for (int i = 0; i < size; i++) {
16+
arr[i] = (long) sc.nextInt();
17+
}
18+
long ways = ways(w);
19+
System.out.println(ways);
20+
}
21+
sc.close();
22+
}
23+
24+
// 用来收集所有输入的数字
25+
public static long[] arr = new long[31];
26+
public static int size = 0;
27+
// 用来生成左部分可能的所有累加和
28+
public static long[] leftSum = new long[1 << 16];
29+
// 准备的数组可能用不完,左部分生成了多少累加和,用leftSize表示
30+
public static int leftSize = 0;
31+
// 用来生成右部分可能的所有累加和
32+
public static long[] rightSum = new long[1 << 16];
33+
// 准备的数组可能用不完,左部分生成了多少累加和,用leftSize表示
34+
public static int rightSize = 0;
35+
36+
public static long ways(long w) {
37+
if (size == 0) {
38+
return 0;
39+
}
40+
if (size == 1) {
41+
return arr[0] <= w ? 2 : 1;
42+
}
43+
// 求中点
44+
int mid = size >> 1;
45+
// 生成左侧的累加和
46+
leftSize = 0;
47+
dfsLeft(0, mid + 1, 0L);
48+
// 生成右侧的累加和
49+
rightSize = 0;
50+
dfsRight(mid + 1, size, 0L);
51+
// 把左侧累加和排序
52+
Arrays.sort(leftSum, 0, leftSize);
53+
// 把右侧累加和排序
54+
Arrays.sort(rightSum, 0, rightSize);
55+
// 解释一下,接下来的流程。
56+
// 举个例子,比如:
57+
// 左侧累加和是:{0, 1, 1, 1, 2, 2, 3, 4, 4}
58+
// 右侧累加和是:{0, 1, 2, 3, 3, 3, 4, 4, 5}
59+
// w = 5
60+
// 左侧严格得到0的方法数:1
61+
// 右侧得到<=5的方法数(二分求出):9
62+
// 1 * 9
63+
// 左侧严格得到1的方法数:3
64+
// 右侧得到<=4的方法数(二分求出):8
65+
// 3 * 8
66+
// 左侧严格得到2的方法数:2
67+
// 右侧得到<=3的方法数(二分求出):6
68+
// 2 * 6
69+
// 左侧严格得到3的方法数:1
70+
// 右侧得到<=2的方法数(二分求出):3
71+
// 1 * 3
72+
// 左侧严格得到4的方法数:2
73+
// 右侧得到<=1的方法数(二分求出):2
74+
// 2 * 2
75+
// 都累加起来
76+
// 其实和课上讲的一样!多看一下例子
77+
long ans = 0;
78+
long count = 1;
79+
for (int i = 1; i < leftSize; i++) {
80+
if (leftSum[i] != leftSum[i - 1]) {
81+
ans += count * (long) find(w - leftSum[i - 1]);
82+
count = 1;
83+
} else {
84+
count++;
85+
}
86+
}
87+
ans += count * (long) find(w - leftSum[leftSize - 1]);
88+
return ans;
89+
}
90+
91+
// 生成左部分的累加和,每一个累加和出来,都记录
92+
public static void dfsLeft(int cur, int end, long sum) {
93+
if (cur == end) { // 已经终止位置了
94+
// 记录累加和
95+
leftSum[leftSize++] = sum;
96+
} else {
97+
// 可能性1,不要当前数
98+
dfsLeft(cur + 1, end, sum);
99+
// 可能性2,要当前数
100+
dfsLeft(cur + 1, end, sum + arr[cur]);
101+
}
102+
}
103+
104+
// 生成右部分的累加和,每一个累加和出来,都记录
105+
public static void dfsRight(int cur, int end, long sum) {
106+
if (cur == end) { // 已经终止位置了
107+
// 记录累加和
108+
rightSum[rightSize++] = sum;
109+
} else {
110+
// 可能性1,不要当前数
111+
dfsRight(cur + 1, end, sum);
112+
// 可能性2,要当前数
113+
dfsRight(cur + 1, end, sum + arr[cur]);
114+
}
115+
}
116+
117+
// <= num的数的个数,返回
118+
public static int find(long num) {
119+
int ans = -1;
120+
int l = 0;
121+
int r = rightSize - 1;
122+
int m = 0;
123+
while (l <= r) {
124+
m = (l + r) / 2;
125+
if (rightSum[m] <= num) {
126+
ans = m;
127+
l = m + 1;
128+
} else {
129+
r = m - 1;
130+
}
131+
}
132+
return ans + 1;
133+
}
134+
135+
}

0 commit comments

Comments
 (0)