目录
E. Increasing Subsequences
题目描述:
思路解析:
看到数据范围 2 - 1e18,首先想到一般方法无法解决,肯定要往二进制方法方面靠。
然后想到二进制后,开始找规律,可以发现 :
1位递增串可以解决2个递增序列,
2位递增串可以解决4个递增序列,
3位递增串可以解决8个递增序列,符合二进制,那么其中包含的递增序列都重复的包含了空串这个递增序列,那么其实1位可以解决一个递增序列,2位可以解决三个递增序列,3位可以解决七个递增序列。其实也可以暗含的转为二进制(都多余的加一位)。
这种方法可行,但是因为题目要求数组长度只能为 [1,200],那么这个方法会超数组范围,因为我们是根据二进制位一位一位解决的,每位之间的信息没有关联起来。假如我们解决1101(二进制)这个数字,我们是单独的处理这四位,这四位之间没有联系。
1101(二进制) --- 答案1: 4 5 3 0 1 2 -1 答案2: 1 -1 2 3 -2
那如何让每位联系起来,来节省空间,观察 4 5 3这个序列可以发现,当序列为4,可以解决两个递增序列,当序列为4 5,可以解决4个递增序列,当序列为 4 5 3可以解决五个递增序列。
从中又可以发现,如果当一个序列 X,可以解决Y个递增序列,序列X的最大值为max,最小值为min,那么 序列F={X, max + 1}可以解决2*Y个递增序列,那么G={X, min-1}可以解决Y+1个递增序列。此时又用到了每位之间的关联,又体现了二进制,问题解决。
代码实现:
方案1:会超数组长度200的限制
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
Scanner input = new Scanner(System.in);
int t = input.nextInt();
for (int o = 0; o < t; o++) {
long x = input.nextLong();
x -= 1;
int p = 1;
int max = 1000;
int[] res = new int[2500];
int size = 0;
while (x > 0){
if ((x & 1) == 1){
int m = size + p - 2;
size = size + p - 1;
for (int i = 0; i < p - 1; i++) {
res[m--] = max--;
}
res[size++] = max--;
}
p++;
x >>= 1;
}
System.out.println(size);
for (int i = 0; i < size; i++) {
System.out.print(res[i] + " ");
}
System.out.println();
}
}
}
方案2:可行答案:
import java.io.*;
import java.util.*;
public class Main {
static int size = 0;
static int mx = 0;
static int my = 0;
static int[] res;
public static void main(String[] args) throws IOException {
Scanner input = new Scanner(System.in);
int t = input.nextInt();
for (int o = 0; o < t; o++) {
long x = input.nextLong();
mx = 0;
size = 0;
my = 0;
res = new int[2500];
dfs(x);
System.out.println(size);
for (int i = 0; i < size; i++) {
System.out.print(res[i] + " ");
}
System.out.println();
}
}
public static void dfs(long x) {
if (x == 1) return;
if (x % 2 == 1){
dfs(x - 1);
res[size++] = --mx;
}else {
dfs(x >> 1);
res[size++] = ++my;
}
}
}