NENU 蓝桥杯训练赛(简单模拟+思维)题解

NENU 蓝桥杯训练赛(简单模拟+思维)题解

NENU 蓝桥杯训练赛(简单模拟+思维)

A Chocolate Thief

题意:

n n n 个学生,每个学生有一块巧克力, x , y , z x,y,z x,y,z 为巧克力的长、宽、高 。每个学生的巧克力长、宽、高可能不同,但体积是相同的。假设学生里最多有一个小偷,如果有小偷,他从另一个学生那里拿走了一部分巧克力。问是否有小偷?

思路:

找到体积的最大值 M a x Max Max 和最小值 M i n Min Min 。如果 M a x = = M i n Max == Min Max==Min ,则没有小偷;否则, 体积为 M a x Max Max 的学生偷了体积为 M i n Min Min 的学生的巧克力。

import java.util.*;
import java.math.*;

public class Main {
	class stu{
		String name;
		int v;
		void setname(String name) {
			this.name = name;
		}
	}
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		String a[] = new String[105];
		int b[] = new int[105];
		for(int ca = 1; ca <= t; ++ca){
			int n = cin.nextInt();
			int sm = 0;
			for(int i = 1;i <= n; ++i) {
				a[i] = cin.next();
				int x = cin.nextInt();
				int y = cin.nextInt();
				int z = cin.nextInt();
				b[i] = x * y * z;
				sm += b[i];
			}
			String p1 = "",p2 = "";
			int avg = sm / n;
			for(int i = 1;i <= n; ++i) {
				if(b[i] > avg) {
					p1 = a[i];
				}
				else if(b[i] < avg){
					p2 = a[i];
				}
			}
			if(p1.equals("") && p2.equals("")) {
				System.out.println("Case " + ca + ": no thief");
			}
			else System.out.println("Case " + ca + ": " + p1 + " took chocolate from " + p2);
		}
		cin.close();
	}
}

B Hidden Secret!

题意:

给定两个字符串,问对这两个字符串进行如下操作后,其是否相同?

  • 可以把一些大写字母改成小写,反之亦然。
  • 可以自由添加/删除空格。
  • 可以排列字母。

思路:

对字符串进行如下操作,然后进行判断。

  • 删除字符串中的空格 。
  • 所有字母都变为小写。
  • 对字符串按字典序升序排序。
import java.util.*;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		char m1[] = new char[30];
		char m2[] = new char[30];
		cin.nextLine();
		for(int ca = 1; ca <= t; ++ca){
			for(int i = 0;i < 26; ++i) {
				m1[i] = m2[i] = 0;
			}
			String s1 = cin.nextLine();
			String s2 = cin.nextLine();
			s1 = s1.toLowerCase();
			s2 = s2.toLowerCase();
			s1 = s1.replace(" ","");
			s2 = s2.replace(" ","");
			char t1[] = s1.toCharArray();
			char t2[] = s2.toCharArray();
			Arrays.sort(t1);
			Arrays.sort(t2);
			s1 = String.valueOf(t1);
			s2 = String.valueOf(t2);
			System.out.println("Case " + ca + ": " + (s1.equals(s2) ? "Yes" : "No"));
		}
		cin.close();
	}
}

C Scarecrow

题意:

1 × N 1 \times N 1×N 的格子, . . . 是有作物的格子, # \# # 是没有作物格子,为了保护作物要在格子上放稻草人,每个稻草人可以保护它当前格和相邻格的作物。问至少需要多少个稻草人去保护作物?

思路:

用最少的稻草人去覆盖 . . . 的格子,每个稻草人可以连续覆盖三个格子,贪心考虑在 . . . 的格子上放稻草人一定不会比在 # \# # 的格子上放稻草人差。从前往后遍历格子,判断当前格子是不是 . . . ,如果是则往跳后三格。

import java.util.*;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		for(int ca = 1; ca <= t; ++ca){
			int n = cin.nextInt();
			String tmp = cin.next();
			char[] str = tmp.toCharArray();
			int ans = 0;
			for(int i = 0;i < n; ) {
				if(str[i] == '.') {
					ans++;
					i += 3;
				}
				else {
					++i;
				}
			}
			System.out.println("Case " + ca + ": " + ans);
		}
		cin.close();
	}
}

D Again Array Queries

题意:

给定 n n n 个数, q q q 次询问,每次给两个数 i , j i,j i,j ,问区间 [ i , j ] [i,j] [i,j] 任意两数的最小差值是多少?

思路:

考虑到 n n n 个数的范围为 [ 1 , 1000 ] [1,1000] [1,1000] ,根据鸽巢原理可知,如果 j − i + 1 > 1000 j - i + 1 > 1000 ji+1>1000 ,最小差值为 0 0 0 ;否则,可以利用桶排序去暴力判断 [ i , j ] [i,j] [i,j] 的最小差值。

import java.util.*;
import java.math.*;

public class Main {
	static int a[] = new int[100005];
	static int b[] = new int[1005];
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		for(int ca = 1; ca <= t; ++ca){
			int n = cin.nextInt();
			int q = cin.nextInt();
			for(int i = 0;i < n; ++i) {
				a[i] = cin.nextInt();
			}
			System.out.println("Case " + ca + ": ");
			int l, r;
			
			while(q-- > 0) {
				l = cin.nextInt();
				r = cin.nextInt();
				System.out.println(calc(l, r));
			}
		}
		cin.close();
	}
	public static int calc(int l, int r) {
		if(r - l + 1 >= 1000) {
			return 0;
		}
		for(int i = 1;i <= 1000; ++i) {
			b[i] = 0;
		}
		for(int i = l;i <= r; ++i) {
			b[a[i]]++;
			if(b[a[i]] > 1) return 0;
		}
		int mn = 1005, pre = 0;
		for(int i = 1;i <= 1000; ++i) {
			if(b[i] > 0) {
				if(pre > 0) {
					mn = Math.min(i - pre, mn);
					pre = i;
				}
				else {
					pre = i;
				}
			}
		}
		return mn;
	}
}

E Scenes From a Memory

题意:

给定一个 k k k 位数,问可不可以删除一些位,让得到的数是一个非素数?

思路:

猜测这样的数不会超过 3 3 3 位,暴力判断 [ 1 , 3 ] [1,3] [1,3]位数。打表验证,这样的数不会超过 2 2 2 位。

import java.util.*;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		long a[] = new long[100005];
		for(int ca = 1; ca <= t; ++ca){
			int n = cin.nextInt();
			String s = cin.next();
			calc(s, n);
		}
		cin.close();
	}
	public static boolean isPrime(int x) {
		if(x == 1)return false;
		for(int i = 2;i * i <= x; ++i) {
			if(x % i == 0)return false;
		}
		return true;
	}
	public static void calc(String s, int n) {
		for(int i = 0; i < s.length(); ++i) {
			int now = (int)(s.charAt(i) - '0');
			if(!isPrime(now)) {
				System.out.println("1" + '\n' + now);
				return ;
			}
		}
		for(int i = 0;i < s.length(); ++i) {
			for(int j = i + 1;j < s.length(); ++j) {
				int now = (int)(s.charAt(i) - '0') * 10 + (int)(s.charAt(j) - '0');
				if(!isPrime(now)) {
					System.out.println("2" + '\n' + now);
					return ;
				}
			}
		}
		for(int i = 0;i < s.length(); ++i) {
			for(int j = i + 1;j < s.length(); ++j) {
				for(int k = j + 1;k < s.length(); ++k) {
					int now = (int)(s.charAt(i) - '0') * 100 + (int)(s.charAt(j) - '0') * 10 + (int)(s.charAt(k) - '0');
					if(!isPrime(now)) {
						System.out.println("3" + '\n' + now);
						return ;
					}
				}
			}
		}
	}
}

F Maximum Product

题意:

给定 n n n 个数,任意取 5 5 5 个数其乘积最大是多少?

思路:

0 0 0 剔除后按升序排序得到数组 a [ 1... k ] a[1...k] a[1...k],如果少于 5 5 5 个数,直接输出 0 0 0
否则,取如下值的最大值:

  • a [ k − 4 ] × a [ k − 3 ] × a [ k − 2 ] × a [ k − 1 ] × a [ k ] a[k-4] \times a[k-3] \times a[k-2] \times a[k-1] \times a[k] a[k4]×a[k3]×a[k2]×a[k1]×a[k]
  • a [ 1 ] × a [ 2 ] × a [ k − 2 ] × a [ k − 1 ] × a [ k ] a[1] \times a[2] \times a[k-2] \times a[k-1] \times a[k] a[1]×a[2]×a[k2]×a[k1]×a[k]
  • a [ 1 ] × a [ 2 ] × a [ 3 ] × a [ 4 ] × a [ k ] a[1] \times a[2] \times a[3] \times a[4] \times a[k] a[1]×a[2]×a[3]×a[4]×a[k]
import java.util.*;
import java.math.*;

public class Main {
	static long a[] = new long[100005];
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		for(int ca = 1; ca <= t; ++ca){
			int n = cin.nextInt();
			for(int i = 1;i <= n; ++i) {
				a[i] = cin.nextLong();
			}
			Arrays.sort(a, 1, n + 1);
			System.out.println(calc(n));
		}
		cin.close();
	}
	public static long calc(int n) {
		long ans = a[1] * a[2] * a[3] * a[4] * a[5];
		for(int i = 1;i <= n - 4; ++i) {
			ans = Math.max(ans, a[i] * a[i + 1] * a[i + 2] * a[i + 3] * a[i + 4]);
		}
		for(int i = 1;i <= n - 4; ++i) {
			ans = Math.max(ans, a[i] * a[i + 1] * a[n - 2] * a[n - 1] * a[n]);
		}
		for(int i = 1;i <= n - 4; ++i) {
			ans = Math.max(ans, a[i] * a[i + 1] * a[i + 2] * a[i + 3] * a[n]);
		}
		return ans;
	}
}

G Sifid and Strange Subsequences

题意:

给定 a [ 1... n ] a[1...n] a[1...n] ,从中选出一些数 b [ 1... m ] b[1...m] b[1...m] b [ i ] ∈ a [ 1... n ] b[i] \in a[1...n] b[i]a[1...n] ,满足对于任意的 i , j i,j i,j ∣ b [ i ] − b [ j ] ∣ ≥ m a x ( b [ 1... n ] ) |b[i] - b[j]| \ge max(b[1...n]) b[i]b[j]max(b[1...n]) , 求 m m m 的最大值?

思路:

a [ 1... n ] a[1...n] a[1...n] 按升序排序后,贪心考虑先把负数和 0 0 0 取出来,然后求出 m i n ( ∣ b [ i ] − b [ j ] ∣ ) min(|b[i]-b[j]|) min(b[i]b[j]) ,再取满足条件的正数,同时不断更新 m i n ( ∣ b [ i ] − b [ j ] ∣ ) min(|b[i]-b[j]|) min(b[i]b[j])

import java.util.*;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		long a[] = new long[100005];
		for(int ca = 1; ca <= t; ++ca){
			int n = cin.nextInt();
			for(int i = 1; i <= n; ++i) {
				a[i] = cin.nextLong();
			}
			Arrays.sort(a, 1, n + 1);
			
			int ans = 1, pos = n;
			for(int i = 0;i < n; ++i) {
				if(i + 1 > n || a[i + 1] > 0) {
					pos = i;
					break;
				}
			}
			if(pos != 0) {
				ans = pos;
				long mn = 2000000000;
				for(int i = 2;i <= pos; ++i) {
					mn = Math.min(mn, a[i] - a[i -  1]);
				}
//				System.out.println("mn = " + mn);
				long pre = a[pos];
				for(int i = pos + 1;i <= n; ++i) {
					mn = Math.min(mn, a[i] - pre);
					pre = a[i];
					if(a[i] <= mn) {
						ans++;
					}
					else {
						break;
					}
				}
			}
			System.out.println(ans);
		}
		cin.close();
	}
}

H Nastia and Nearly Good Numbers

题意:

给定两个正整数 A , B A,B A,B ,问是否能找到三个不同的数 x , y , z x,y,z x,y,z ,使得 x + y = z x+y=z x+y=z x , y , z x,y,z x,y,z 满足以下条件:

  • 如果一个整数能够整除 A × B A \times B A×B ,那么它是好的。
  • 否则,如果一个整数能够整除 A A A ,那么它是几乎好的。

x , y , z x,y,z x,y,z 中要有一个数是好的,另外两个数是几乎好的。

思路:

  • B = 1 B=1 B=1 ,无解。
  • B = 2 B=2 B=2 x = A , y = A × 3 , z = A × 4 x=A,y=A \times 3,z=A \times 4 x=A,y=A×3,z=A×4
  • B > 2 B > 2 B>2 x = A , y = A × ( B − 1 ) , z = A × B x=A,y=A \times (B-1),z=A \times B x=A,y=A×(B1),z=A×B
import java.util.*;
import java.math.*;

public class Main {
	class stu{
		String name;
		int v;
		void setname(String name) {
			this.name = name;
		}
	}
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		String a[] = new String[105];
		int b[] = new int[105];
		for(int ca = 1; ca <= t; ++ca){
			long A = cin.nextLong();
			long B = cin.nextLong();
			if(B == 1) {
				System.out.println("NO");
			}
			else if(B == 2) {
				System.out.println("YES" + '\n' + A  + ' ' + A * 3 + ' ' + A * 4);
			}
			else {
				System.out.println("YES" + '\n' + A + ' ' + A * (B - 1) + ' ' + A * B);
			}
		}
		cin.close();
	}
}

I A-B Palindrome

题意:

给定一个由 0 , 1 , ? 0,1,? 0,1,? 构成的字符串和 a a a 0 0 0 b b b 1 1 1 ,你可以在 ? ? ? 的位置填 0 , 1 0,1 0,1 ,问使得填完之后的字符串是否是回文串。

思路:

  • 判断给定的字符串是否回文,即 0 0 0 0 0 0 1 1 1 1 1 1
  • 根据回文的性质暴力填 0 , 1 0,1 0,1 ,与 0 0 0 对应的 ? ? ? 0 0 0 ,与 1 1 1 对应的 ? ? ? 1 1 1 。填完之后看 0 , 1 0,1 0,1 是否用超了。
  • 最后再把 ? ? ? 对应 ? ? ? 的位置填完。
import java.util.*;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		char s[] = new char[400005];
		for(int ca = 1; ca <= t; ++ca){
			int na = cin.nextInt();
			int nb = cin.nextInt();
			cin.nextLine();
			String str = cin.nextLine();
			s = str.toCharArray();
			int flag = 0;
			for(int i = 0, j = s.length - 1; i <= j; ++i, --j) {
				if(s[i] != '?') {
					if(s[j] == '?')s[j] = s[i];
					else if(s[i] != s[j]){
						flag = 1;
						break;
					}
				}
				else if(s[j] != '?') {
					if(s[i] == '?')s[i] = s[j];
				}
			}
			if(flag == 1) {
				System.out.println("-1");
				continue;
			}
			int nowa = 0, nowb = 0;
			for(int i = 0;i < s.length; ++i) {
				if(s[i] == '0')nowa++;
				else if(s[i] == '1')nowb++;
			}
			if(nowa > na || nowb > nb) {
				System.out.println("-1");
				continue;
			}
			nowa = na - nowa;
			nowb = nb - nowb;
			for(int i = 0, j = s.length - 1; i <= j; ++i, --j) {
				if(s[i] == '?') {
					if(i != j) {
						if(nowa > 1) {
							s[i] = s[j] = '0';
							nowa -= 2;
						}
						else if(nowb > 1) {
							s[i] = s[j] = '1';
							nowb -= 2;
						}
					}
					else if(i == j) {
						if(nowa > 0) {
							s[i] = '0';
							nowa--;
						}
						else if(nowb > 0) {
							s[i] = '1';
							nowb--;
						}
					}
				}
			}
			if(nowa == 0 && nowb == 0) {
				for(int i = 0; i < s.length; ++i) {
					System.out.print(s[i]);
				}
				System.out.println("");
			}
			else {
				System.out.println("-1");
			}
		}
		cin.close();
	}
	
}

J Repainting Street

题意:

n n n 个有颜色的房子,第 i i i 个房子的颜色为 c i c_i ci 。Tom每天可以把连续 k k k 个房子涂成同一种颜色,问最少多少天可以把所有房子涂成同一种颜色?

思路:

c i ∈ [ 1 , 100 ] c_i \in [1,100] ci[1,100] ,可以暴力把所有房子涂成100种颜色分别需要多少时间算出来,然后取最小值。(该题跟C稻草人那题差不多,模改一下代码即可)

import java.util.*;
import java.math.*;

public class Main {
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		int c[] = new int[100010];
		for(int ca = 1; ca <= t; ++ca){
			int n = cin.nextInt();
			int k = cin.nextInt();
			for(int i = 1;i <= n; ++i) {
				c[i] = cin.nextInt();
			}
			int ans = n;
			for(int color = 1; color <= 100; ++color) {
				int now = 0;
				for(int i = 1;i <= n; ) {
					if(c[i] != color) {
						i += k;
						now++;
					}
					else {
						i++;
					}
				}
				if(now < ans)ans = now;
			}
			System.out.println(ans);
		}
		cin.close();
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值