A. 攻击次数
image-20250420152350082
image-20250420152350082
这题有歧义,如果考虑三个英雄一起上,就是103,考虑一回合只能上一个伤害高的,就是181
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Main { public static void main (String[] args) { int hp = 2025 ; int cnt = 0 ; while (hp > 0 ){ cnt++; int hero1 = 5 ; int hero2 = (cnt % 2 == 1 ) ? 15 : 2 ; int hero3 = 0 ; if (cnt % 3 == 1 ){ hero3 = 2 ; }else if (cnt % 3 == 2 ){ hero3 = 10 ; }else if (cnt % 3 == 0 ){ hero3 = 7 ; } hp -= hero1 + hero2 + hero3; } System.out.println(cnt); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 n = 0 i = 1 while n < 2025 : if i & 1 : n += 15 else : if i % 3 == 2 : n += 10 elif i % 3 == 0 : n += 7 else : n += 5 i += 1 print (i - 1 )
B. 最长字符串
image-20250420152634843
image-20250420152634843
下载附件 words.txt
优美字符串的定义是:字符串本身存在于给定的单词列表中,并且可以通过调整顺序后由另一个更短的优美字符串扩展而来。
考的主要是文件读写,默认把 txt 附件存在和代码同级别的目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 package 基础算法和其他.IO读写流.P12171_蓝桥杯_2025_省_Python_B_最长字符串;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.util.*;public class Main { public static void main (String[] args) { List<String> words = new ArrayList <>(); try (BufferedReader br = new BufferedReader (new FileReader ("D:\\WorkSpace\\JavaDemo\\IDEA\\Algorithm\\src\\字符串\\subject\\P12171_蓝桥杯2025省PythonB最长字符串\\words.txt" ))){ String line; while ((line = br.readLine()) != null ) { words.add(line.trim()); } }catch (IOException e){ e.printStackTrace(); } words.sort(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder())); Set<String> bs = new HashSet <>(); for (String word : words){ if (word.length() == 1 ){ bs.add(word); }else { String pre = sortString(word.substring(0 , word.length() - 1 )); for (String sbs: bs){ if (sortString(sbs).equals(pre)){ bs.add(word); break ; } } } } int maxLength = 0 ; for (String word : bs) { maxLength = Math.max(maxLength, word.length()); } List<String> ls = new ArrayList <>(); for (String word : bs) { if (word.length() == maxLength) { ls.add(word); } } ls.sort(Comparator.naturalOrder()); System.out.println(ls.get(0 )); } private static String sortString (String s) { char [] charArray = s.toCharArray(); Arrays.sort(charArray); return new String (charArray); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 with open ("words.txt" , "r" ) as f: ws = [line.strip() for line in f] ws.sort(key=lambda x: (len (x), x)) bs = set () for w in ws: if len (w) == 1 : bs.add(w) else : pre = '' .join(sorted (w[:-1 ])) if any ('' .join(sorted (s)) == pre for s in bs): bs.add(w) ml = max (len (w) for w in bs) lbs = [w for w in bs if len (w) == ml] print (min (lbs))
C. LQ图形
img
img
img
img
观察可发现,可以将L分为上下两个部分,上面列数少的为h行,下面列数多的为w行,上下宽度分别为w和v+w。时间复杂度O(h
+ w)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); int w = sc.nextInt(); int h = sc.nextInt(); int v = sc.nextInt(); StringBuilder sb1 = new StringBuilder (); StringBuilder sb2 = new StringBuilder (); for (int i = 1 ; i <= w; i++) sb1.append('Q' ); for (int i = 1 ; i <= v + w; i++) sb2.append('Q' ); for (int i = 1 ; i <= h; i++) System.out.println(sb1); for (int i = 1 ; i <= w; i++) System.out.println(sb2); } }
1 2 3 4 5 6 7 w,h,v = MII() t = h b = w for i in range (t): print ('Q' * w) for i in range (b): print ('Q' * (v + w))
D. 最多次数
img
img
贪心,遇到连续的三个某个顺序的 l,q,b, 就把他拿掉。时间复杂度O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); String str = sc.nextLine(); String[] strs = {"lqb" , "lbq" , "qlb" , "qbl" , "blq" , "bql" }; int res = 0 , index = 0 ; for (int i = 0 ; i < str.length() - 2 ; i++){ String sub = str.substring(i, i + 3 ); for (int j = 0 ; j < 6 ; j++){ if (sub.equals(strs[j])){ i += 2 ; res++; break ; } } } System.out.println(res); sc.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 str_input = input () strs = ["lqb" , "lbq" , "qlb" , "qbl" , "blq" , "bql" ] res = 0 i = 0 while i < len (str_input) - 2 : sub = str_input[i:i + 3 ] for j in range (6 ): if sub == strs[j]: i += 2 res += 1 break i += 1 print (res)
E. A*B Problem
在这里插入图片描述
在这里插入图片描述
给定 n,求四元组 (a,b,c,d) 个数,满足 a×b+c×d≤n,且 a,b,c,d
都是正整数。
我们需要枚举所有可能的向量 A 和 B,使得它们的内积不超过 L。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner scanner = new Scanner (System.in); int L = scanner.nextInt(); int count = 0 ; for (int XA = 1 ; XA <= L; XA++) { for (int YA = 1 ; YA <= L; YA++) { for (int XB = 1 ; XB <= L / XA + 1 ; XB++) { for (int YB = 1 ; YB <= (L - XA * XB) / YA + 1 ; YB++) { if (XA * XB + YA * YB <= L) { count++; } } } } } System.out.println(count); } }
不行,只有80分,考虑优化
将四元组 (a,b,c,d) 的问题转化为两个部分:x=a×b和 y=c×d,使得
x+y≤n。
这样,问题转化为统计所有满足 x+y≤n 的正整数对 (x,y) 的数量,其中 x 和
y 都可以表示为两个正整数的乘积。
这样对于满足 x+y=k 的四元组个数就是 tx×ty。
考虑每个数 i,预处理其能表示为两个正整数乘积的方式数 t[i](即 i
的因数对数)。把 x 打表打出来
使用线性筛法预处理每个数的因数个数,计算 t[i]。
计算 t[i] 的前缀和数组 s[i],用于快速查询 y≤n−x 时的 t[y]
的总和。
对于每个 x,其贡献为 t[x]×s[n−x]
为什么求 t[y] 要使用前缀和数组,对于每个固定的
x,我们需要找到所有满足 y≤n−x 的 y 的数量,也就是 ∑y=1n−xt[y]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package 数学.subject.P12174_蓝桥杯2025 省Python_B_AxBProblem;import java.util.Arrays;import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); int l = sc.nextInt(); int [] t = new int [l + 1 ]; Arrays.fill(t, 0 ); for (int a = 1 ; a <= l; a++) { for (int b = 1 ; a * b <= l; b++){ t[a * b]++; } } int [] s = new int [l + 1 ]; s[0 ] = 0 ; for (int i = 1 ; i <= l; i++) { s[i] = s[i - 1 ] + t[i]; } long total = 0 ; for (int x = 1 ; x < l; x++){ int y = l - x; total += (long )t[x] * s[y]; } System.out.println(total); } }
F. 园艺
讲过了,在
G. 书架还原
在这里插入图片描述
在这里插入图片描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package 基础算法和其他.贪心.subject.P12176_蓝桥杯2025 省PythonB_书架还原;import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); int n = sc.nextInt(); int [] a = new int [n + 1 ]; int [] p = new int [n + 1 ]; int res = 0 ; for (int i = 1 ; i <= n; i++){ a[i] = sc.nextInt(); p[a[i]] = i; } for (int i = 1 ; i <= n; i++){ if (a[i] != i){ p[a[i]] = p[i]; ++res; int temp = a[p[i]]; a[p[i]] = a[i]; a[i] = temp; } } System.out.println(res); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 n = II() a = [0 ] + LII() p = [0 ] * (n + 1 ) res = 0 for i in range (1 ,n + 1 ): p[a[i]] = i for i in range (1 ,n + 1 ): if a[i] != i: p[a[i]] = p[i] a[i],a[p[i]] = a[p[i]],a[i] res += 1 print (res)
H. 异或和
在这里插入图片描述
在这里插入图片描述
考虑位运算,把每个数拆成二进制然后进行统计
由于异或运算本身就是建立在位的基础上的,所以我们只需要用一层循环枚举位
只有两个数当前位不同才能产生贡献。也就是说,如果这一位是
0,那他得跟这一位为 1 的数异或才能有贡献,所以加上这一位为 1
的数的个数再乘以这一位的权值
如果先不考虑公式后面的 j−i,那么只有用两个变量统计每位 0 和 1
的个数。
现在还得乘上 j−i,这个值是不断变化的,可以发现其中 i 是不变的,j
每次只加1,开两个变量存储每位 0 和 1 的权值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.math.BigInteger;import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner sc = new Scanner (System.in); int n = sc.nextInt(); BigInteger[] arr = new BigInteger [n + 1 ]; for (int i = 1 ; i <= n; i++) { arr[i] = sc.nextBigInteger(); } BigInteger res = BigInteger.ZERO; for (int dig = 0 ; dig <= 20 ; dig++) { int [] cnt = {0 , 0 }; BigInteger[] sum = {BigInteger.ZERO, BigInteger.ZERO}; for (int i = 1 ; i <= n; i++) { int bit = arr[i].shiftRight(dig).and(BigInteger.ONE).intValue(); BigInteger multiplier = BigInteger.valueOf(1L << dig); res = res.add(sum[bit ^ 1 ].multiply(multiplier)); cnt[bit]++; sum[0 ] = sum[0 ].add(BigInteger.valueOf(cnt[0 ])); sum[1 ] = sum[1 ].add(BigInteger.valueOf(cnt[1 ])); } } System.out.println(res); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 n = int (input ()) a = list (map (int , input ().split())) res = 0 for b in range (31 ): m = 1 << b c = [0 , 0 ] s = [0 , 0 ] cur = 0 for i in range (n): bit = (a[i] >> b) & 1 cur += c[1 - bit] * i - s[1 - bit] c[bit] += 1 s[bit] += i res += cur * m print (res)