Day8
第一题
第五届2014年蓝桥杯省赛
神奇算式
JavaA组第3题
填空题
利用Set
集合去重,并判断set
的大小是否为4
。
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
int cnt = 0;
for (int i = 1; i <= 987; i++) {
for (int j = i; j <= 987; j++) {
int res = i * j;
if (res >= 10000) continue;
String s1 = i + "" + j;
String s2 = res + "";
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
if (check(c1, c2)) cnt++;
}
}
System.out.println(cnt);
}
private static boolean check(char[] c1, char[] c2) {
Arrays.sort(c1);
Arrays.sort(c2);
String s1 = String.valueOf(c1);
String s2 = String.valueOf(c2);
if (s1.equals(s2) && check_reduplicate(s2)) {
return true;
}
return false;
}
// 判重
private static boolean check_reduplicate(String s) {
Set<String> set = new HashSet<>();
for (int i = 0; i < s.length(); i++) {
set.add(s.charAt(i) + "");
}
if (set.size() == 4) {
return true;
}
return false;
}
}
第二题
第九届2018年蓝桥杯省赛
缩位求和
JavaC组第6题
简单的字符串处理问题。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String a = sc.next();
while (a.length() > 1) {
int sum = 0;
for (int i = 0; i < a.length(); i++) {
sum += a.charAt(i) - '0'; // 转为int类型
}
String b = sum + ""; // 转为String类型
a = b; // 重新赋值 再次拆分
}
System.out.println(a); // 此时a只剩一位
}
}
第三题
NOIP2013提高组
积木大赛
贪心+差分
给定一个区间,每次操作可以使这个区间所有积木数+1
,现在就是给我们一个大厦的宽度n
以及每1
个宽度需要的积木数,让我们求最少操作多少次可以建成大厦,不难看出是一道贪心题目,使我们的区间尽量大。
我们可以把过程逆过来,因为我们已经知道了每堆积木的高度,所以我们可以将某一段区间所有高度-1
,求我们操作多少次可以把所有高度变为0
。
看第一个样例:
操作所有数,全部-1
再操作前3个数:
再操作第2、3个数:
然后再分别操作第3个数和第5个数,总操作数为5。
我们试着用差分来解决这道题,将原数组 变为差分数组
原数组:
差分数组:
$b_2 = h_2 - h_1 $
$… $
当我们想让区间的所有数 全部-1
,我们只需要改差分数组的两个值就可以,,不变, 减了1,所以 减了1;, 和 都减了1,差值不变,所以 不变,以此类推剩下的都不变,但当 时, 不变, 减了1,所以是让 加了1。
综上,如果对原数组的区间所有值全部减1,那么对应到差分数组我们只改变了两个值:一个是 减1,另一个是 加1。
原数组任意的区间操作都可以对应到差分数组两个数的操作,而且是一一对应的。
我们要使原数组所有数变成0
,那么差分数组也全部变成0
,相当于我们每次要从差分数组 挑两个数,前一个减1,后一个加1,求最少操作多少次可以将所有数变成0。
我们每一次从前往后看,找到第一个大于0的 ,我们从后面任意找一个负数 和 配对,然后让 减1, 加1即可。
我们如何确定我们一定能在 后面找到一个负数呢?
把所有 拆分成原数组,所有项全部都消掉了,只剩下了 。
我们发现:因为所有,所以 一定是小于等于0的,所以当 时, 一定是严格小于0的,所以 后面必然存在一个负数。
综上,证明完毕。
求出差分数组并扫描一遍即可。
时间复杂度
import java.util.Scanner;
public class Main {
static final int N = 100010;
static int[] h = new int[N]; // 原数组
static int[] b = new int[N]; // 差分数组
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++) h[i] = sc.nextInt();
for (int i = 1; i <= n + 1; i++) b[i] = h[i] - h[i - 1]; // 差分数组 i要取到n + 1
int res = 0;
for (int i = 1; i <= n + 1; i++) {
if (b[i] > 0) res += b[i]; // 只要b[i] > 0 我们就至少需要操作一次
}
System.out.println(res);
}
}