蓝桥杯javaB组赛前四天复习-1

一、暴力枚举 / 模拟

1. 两数之和

① HashMap 相关方法:

  • hashmap.containsKey():返回 boolean 类型,用于判断是否包含指定键
  • hashmap.get():获取对应键的 value 值

49. 字母异位词分组

① List 与 Set 区别:

  • List:允许重复、有序,可通过下标 get(i) 获取元素
  • Set:不允许重复、无序,不能通过 get(i) 获取元素

② 字符串转数组方法:

java 复制代码
char[] array = str.toCharArray();

③ 对数组排序:

java 复制代码
Arrays.sort(数组名);

④ List 初始化与使用:

java 复制代码
List<String> list = map.getOrDefault(key, new ArrayList<>());
// list 使用方法

① add(添加元素)

java 复制代码
// 运行
list.add("张三");
list.add("李四");
list.add("王五");
// 现在 list:[张三, 李四, 王五]

② get(获取第几个元素,从 0 开始)

java 复制代码
// 运行
String name = list.get(0); // 获取第 0 个 → "张三"
String name2 = list.get(1); // 获取第 1 个 → "李四"

③ set(修改某个位置的值)

java 复制代码
// 运行
list.remove(0); // 删除下标 0
// 现在 list:[赵六, 王五]

④ remove(删除)

  • 方式 1:按下标删除

    java 复制代码
    // 运行
    list.remove(0); // 删除下标 0
    // 现在 list:[赵六, 王五]
  • 方式 2:按内容删除

    java 复制代码
    // 运行
    list.remove("王五");
    // 现在 list:[赵六]

⑤indexOf(找元素的下标)

java 复制代码
// 运行
int index = list.indexOf("赵六"); // 返回 0
int no = list.indexOf("不存在");  // 找不到返回 -1

⑥ contains(判断是否包含某个元素)

java 复制代码
// 运行
boolean has = list.contains("赵六"); // true
boolean no = list.contains("张三");   // false

① map.keySet()

  • 作用:返回一个包含 Map 中所有键(key)的 Set 集合。
java 复制代码
// 假设已有一个 Map
Map<String, Integer> map = new HashMap<>();
map.put("张三", 20);
map.put("李四", 25);

// 获取所有键的集合
Set<String> keys = map.keySet();

// 遍历所有键
for (String key : keys) {
    System.out.println("键: " + key);
}
// 输出:
// 键: 张三
// 键: 李四

② map.values()

  • 作用:返回一个包含 Map 中所有值(value)的 Collection 集合。

    java 复制代码
    // 假设已有一个 Map
    Map<String, Integer> map = new HashMap<>();
    map.put("张三", 20);
    map.put("李四", 25);
    
    // 获取所有值的集合
    Collection<Integer> values = map.values();
    
    // 遍历所有值
    for (Integer value : values) {
        System.out.println("值: " + value);
    }
    // 输出:
    // 值: 20
    // 值: 25

二、2025年真题

3313.电池分组

1.题目描述

研究员小蓝受到实验室主任的指示,需要对实验室新研发的 N 个新型能量 电池进行分组实验。这 N 个能量电池的能量值分别用 A1, A2, . . . , AN 表示,每个 能量值都是一个整数。为了保证实验的安全性,小蓝需要将这 N 个能量电池分 成两组,使得这两组能量电池的能量值异或和相等。

能量值的异或和计算方法如下:对于一个集合 S,其异或和等于集合中所 有元素的按位异或结果。例如,集合 {1, 2, 3} 的异或和为 1 ⊕ 2 ⊕ 3 = 0,其中 ⊕ 表示异或运算。

现在,小蓝想知道,这 N 个能量电池能否分成两组,使得这两组能量电池 的能量值异或和相等。注意,每组至少包含一个能量电池。

2.输入格式

输入的第一行包含一个整数 T ,表示测试用例的数量。

每个测试用例占两行:

第一行包含一个整数 N,表示能量电池的数量。

第二行包含 N 个整数 A1, A2, . . . , AN,表示每个能量电池的能量值。

3.重要知识点:异或^
1). 什么是 异或(⊕ / XOR)

就是一种 二进制按位计算,规则只有 4 句:

  • 0 ⊕ 0 = 0
  • 0 ⊕ 1 = 1
  • 1 ⊕ 0 = 1
  • 1 ⊕ 1 = 0

口诀:相同为 0,不同为 1

先转二进制:

  • 1 → 01
  • 2 → 10
  • 3 → 11

一步步算:

1 ⊕ 2 = 01 ⊕ 10 = 11(=3)

3 ⊕ 3 = 11 ⊕ 11 = 00(=0)

所以:

1 ⊕ 2 ⊕ 3 = 0

4.代码
java 复制代码
package text;
import java.util.*;
public class test1 {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Scanner scan=new Scanner(System.in);
		int T=scan.nextInt();
		while(T-->0) {
			int N=scan.nextInt();
			int sum=0;
			for(int i=0;i<N;i++) {
				int a=scan.nextInt();
				sum^=a;
				}
			System.out.println(sum==0?"YES":"NO");
			}
	}

}

3314.魔法科考试

找质数:

java 复制代码
  boolean [] isPrime=new boolean[max + 5]; 
        for(int i=2;i<=max;i++) {
            isPrime[i]=true;
        }
        
        for(int i=2;i*i<=max;i++) {
            if(isPrime[i]) {
                for(int j=i*i;j<=max;j+=i) {
                    isPrime[j]=false;
                }	
            }
        }

P1918 保龄球

题目描述

DL 算缘分算得很烦闷,所以常常到体育馆去打保龄球解闷。因为他保龄球已经打了几十年了,所以技术上不成问题,于是他就想玩点新花招。

DL 的视力真的很不错,竟然能够数清楚在他前方十米左右每个位置的瓶子的数量。他突然发现这是一个炫耀自己好视力的借口------他看清远方瓶子的个数后从某个位置发球,这样就能打倒一定数量的瓶子。

如上图,每个 " ◯ \bigcirc ◯" 代表一个瓶子。如果 DL 想要打倒 3 3 3 个瓶子就在 1 1 1 位置发球,想要打倒 4 4 4 个瓶子就在 2 2 2 位置发球。

现在他想要打倒 m m m 个瓶子。他告诉你每个位置的瓶子数,请你给他一个发球位置。

输入格式

第一行包含一个正整数 n n n,表示位置数。

第二行包含 n n n 个正整数 a i a_i ai ,表示第 i i i 个位置的瓶子数,保证各个位置的瓶子数不同。

第三行包含一个正整数 Q Q Q,表示 DL 发球的次数。

第四行至文件末尾,每行包含一个正整数 m m m,表示 DL 需要打倒 m m m 个瓶子。

输出格式

共 Q Q Q 行。每行包含一个整数,第 i i i 行的整数表示 DL 第 i i i 次的发球位置。若无解,则输出 0 0 0。

输入输出样例 #1

输入 #1

复制代码
5
1 2 4 3 5
2
4
7

输出 #1

复制代码
3
0

说明/提示

【数据范围】

对于 50 % 50\% 50% 的数据, 1 ≤ n , Q ≤ 1000 , 1 ≤ a i , m ≤ 10 5 1 \leq n, Q \leq 1000, 1 \leq a_i, m \leq 10^5 1≤n,Q≤1000,1≤ai,m≤105。

对于 100 % 100\% 100% 的数据, 1 ≤ n , Q ≤ 100000 , 1 ≤ a i , m ≤ 10 9 1 \leq n,Q \leq 100000, 1 \leq a_i, m \leq 10^9 1≤n,Q≤100000,1≤ai,m≤109。

代码:

java 复制代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.*;
public class Main {

	public static void main(String[] args) throws IOException {
		// TODO 自动生成的方法存根
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int n=Integer.parseInt(br.readLine());
		Map <Integer,Integer> map=new HashMap<>();
		StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
        int a;
		for(int i=1;i<=n;i++) {
			a=Integer.parseInt(stringTokenizer.nextToken());
			map.put(a, i);
		}
		int Q=Integer.parseInt(br.readLine());
		int [] arr=new int[Q];
		
		for(int i=0;i<Q;i++) {
			arr[i]=Integer.parseInt(br.readLine());
		}
		StringBuilder sBuilder=new StringBuilder();
		for(int b:arr) {
			if(map.containsKey(b)) {
				sBuilder.append(map.get(b)).append("\n");
			}else {
				sBuilder.append("0\n");
			}
		}
		System.out.println(sBuilder);
	}

}

!NOTE

🔥 终极口诀(背这个)

  • 一行只有一个数 → 用 br.readLine()
  • 一行有好多个数 → 用 StringTokenizer + nextToken()

!CAUTION

当出现MLE的时候可以采用快读快写的方式,但是要注意的是main方法后面要添加·throws IOException·

P1102 A-B 数对

时间限制: 1.00s 内存限制: 125.00MB

复制 Markdown\](javascript:void 0) \[ 中文\](javascript:void 0) \[ 退出 IDE 模式\](javascript:void 0) ### 题目背景 出题是一件痛苦的事情! 相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈! ### 题目描述 给出一串正整数数列以及一个正整数 *C* ,要求计算出所有满足 *A* −*B* =*C* 的数对的个数(不同位置的数字一样的数对算不同的数对)。 ### 输入格式 输入共两行。 第一行,两个正整数 *N* ,*C*。 第二行,*N* 个正整数,作为要求处理的那串数。 ### 输出格式 一行,表示该串正整数中包含的满足 *A* −*B* =*C* 的数对的个数。 ### 输入输出样例 **输入 #1**复制运行 4 1 1 1 2 3 **输出 #1**复制运行 3 ### 说明/提示 对于 75% 的数据,1≤*N*≤2000。 对于 100% 的数据,1≤*N* ≤2×105,0≤*a\*\*i* \<230,1≤*C*\<230。 2017/4/29 新添数据两组 #### 代码 ```java import java.util.*; import java.io.*; public class Main { public static void main(String[] args) throws IOException { // TODO 自动生成的方法存根 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st=new StringTokenizer(br.readLine()); int N=Integer.parseInt(st.nextToken()); long C=Long.parseLong(st.nextToken()); st=new StringTokenizer(br.readLine()); long []arr=new long[N]; Map map=new HashMap<>(); for(int i=0;i map=new HashMap<>(); while(Q-->0){ String [] s=br.readLine().split(" "); String op=s[0]; if(op.equals("1")){ map.put(s[1],Long.parseLong(s[2])); bw.write("OK\n"); }else if(op.equals("2")){ if(map.containsKey(s[1])){ bw.write(map.get(s[1])+"\n"); }else{ bw.write("Not found\n"); } }else if(op.equals("3")){ if(map.containsKey(s[1])){ map.remove(s[1]); bw.write("Deleted successfully\n"); }else{ bw.write("Not found\n"); } }else{ bw.write(map.size()+"\n"); } bw.flush(); } } } ``` ## P5250 【深基17.例5】木材仓库 ### 题目描述 博艾市有一个木材仓库,里面可以存储各种长度的木材,但是保证没有两个木材的长度是相同的。作为仓库负责人,你有时候会进货,有时候会出货,因此需要维护这个库存。有不超过 10 5 10\^5 105 条的操作: * 进货,格式 `1 Length`:在仓库中放入一根长度为 L e n g t h Length Length(不超过 10 9 10\^9 109)的木材。如果已经有相同长度的木材那么输出 `Already Exist`。 * 出货,格式 `2 Length`:从仓库中取出长度为 L e n g t h Length Length 的木材。如果没有刚好长度的木材,取出仓库中存在的和要求长度最接近的木材。如果有多根木材符合要求,取出比较短的一根。输出取出的木材长度。如果仓库是空的,输出 `Empty`。 ### 输入格式 第一行一个数 m m m 代表操作次数。 接下来 m m m 行,每行一次操作,格式如题目描述所示。 ### 输出格式 对于每次操作,按照题目描述要求输出答案。 ### 输入输出样例 #1 #### 输入 #1 7 1 1 1 5 1 3 2 3 2 3 2 3 2 3 #### 输出 #1 3 1 5 Empty #### 代码 ```java import java.util.*; import java.io.*; public class Main { public static void main(String[] args) throws IOException{ // TODO 自动生成的方法存根 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); int m=Integer.parseInt(br.readLine()); TreeSet tree=new TreeSet<>(); while(m-->0){ String [] a=br.readLine().split(" "); int op=Integer.parseInt(a[0]); int length=Integer.parseInt(a[1]); if(op==1){ if(tree.contains(length)){ bw.write("Already Exist\n"); }else{ tree.add(length); } }else{ if(tree.isEmpty()){ bw.write("Empty\n"); }else if(tree.contains(length)){ tree.remove(length); bw.write(length+"\n"); }else{ Integer pre=tree.floor(length); Integer next=tree.ceiling(length); if(pre==null&&next!=null){ tree.remove(next); bw.write(next+"\n"); }else if(pre!=null&&next==null){ tree.remove(pre); bw.write(pre+"\n"); }else{ if((length-pre)<=(next-length)){ tree.remove(pre); bw.write(pre+"\n"); }else{ tree.remove(next); bw.write(next+"\n"); } } } } } bw.flush(); } } ``` ## U535982 C-小梦的AB交换 ### 题目描述 小梦有一个长度为 2 ∗ n 2 \* n 2∗n 的 A B AB AB 串 s s s,即 s s s 中只包含 " A A A" 和 " B B B" 两种字符,且其中恰好有 n n n 个 " A A A" 和 n n n 个 " B B B"。 他可以对 s s s 执行以下操作: ∙ \\bullet ∙ 选择 i , j ( 1 ≤ i , j ≤ 2 ⋅ n , i ≠ j ) i, j\\ (1 \\leq i, j \\leq 2\\cdot n, i \\ne j) i,j (1≤i,j≤2⋅n,i=j),并交换 s i s_i si 和 s j s_j sj。 他想知道,需要至少多少次操作,才能使得 s s s 满足相邻的字符不相同,请你帮他算一算吧。 ### 输入格式 **本题有多组测试数据。** 输入的第一行包含一个正整数 T T T,表示数据组数。 接下来包含 T T T 组数据,每组数据的格式如下: 第一行一个正整数 n n n,表示 s s s 长度的一半。 第二行一个长度为 2 ∗ n 2\*n 2∗n 的字符串 s s s,保证只由 " A A A", " B B B" 两种字符构成。 ### 输出格式 对于每组测试数据: 在单独的一行输出一个整数,表示最少进行的操作次数。 ### 输入输出样例 #1 #### 输入 #1 2 3 AAABBB 3 ABAABB #### 输出 #1 1 1 ### 说明/提示 **【样例 1 解释】** 交换 s 2 = A s_2 = A s2=A 和 s 5 = B s_5=B s5=B,得到 s = s= s= " A B A B A B \\rm ABABAB ABABAB",满足题意,一次交换即可。 **【数据范围】** 令 N N N 表示 T T T 组数据中 n n n 的总和。 对于 50 % \\rm 50\\% 50% 的数据有: T = 1 , 1 ≤ N ≤ 3 T = 1, 1 \\leq N\\leq 3 T=1,1≤N≤3。 对于所有的测试数据有: 1 ≤ T ≤ 100 , 1 ≤ N ≤ 10 6 1 \\leq T \\leq 100, 1 \\leq N \\leq 10\^6 1≤T≤100,1≤N≤106。 #### 代码 ```java import java.util.*; import java.io.*; public class Main { public static void main(String[] args) throws IOException{ // TODO 自动生成的方法存根 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); int t=Integer.parseInt(br.readLine()); while(t-->0){ int n=Integer.parseInt(br.readLine()); char[] c=br.readLine().toCharArray(); int err1=0; int err2=0; for(int i=0;i<2*n;i++){ char b=c[i]; if(i%2==0){ if(b!='B'){ err1++; } }else{ if(b!='A'){ err1++; } } if(i%2==0){ if(b!='A'){ err2++; } }else{ if(b!='B'){ err2++; } } } System.out.println(Math.min(err1,err2)/2); } } } ``` ## B3612 【深进1.例1】求区间和 ### 题目描述 给定 n n n 个正整数组成的数列 a 1 , a 2 , ⋯   , a n a_1, a_2, \\cdots, a_n a1,a2,⋯,an 和 m m m 个区间 \[ l i , r i \] \[l_i,r_i\] \[li,ri\],分别求这 m m m 个区间的区间和。 ### 输入格式 第一行包含一个正整数 n n n,表示序列的长度。 第二行包含 n n n 个正整数 a 1 , a 2 , ⋯   , a n a_1,a_2, \\cdots ,a_n a1,a2,⋯,an。 第三行包含一个正整数 m m m,表示区间的数量。 接下来 m m m 行,每行包含两个正整数 l i , r i l_i,r_i li,ri,满足 1 ≤ l i ≤ r i ≤ n 1\\le l_i\\le r_i\\le n 1≤li≤ri≤n。 ### 输出格式 共 m m m 行,其中第 i i i 行包含一个正整数,表示第 i i i 组答案的询问。 ### 输入输出样例 #1 #### 输入 #1 4 4 3 2 1 2 1 4 2 3 #### 输出 #1 10 5 ### 说明/提示 #### 样例解释 第 1 1 1 到第 4 4 4 个数加起来和为 10 10 10。第 2 2 2 个数到第 3 3 3 个数加起来和为 5 5 5。 #### 数据范围 对于 50 % 50 \\% 50% 的数据: n , m ≤ 1000 n,m\\le 1000 n,m≤1000; 对于 100 % 100 \\% 100% 的数据: 1 ≤ n , m ≤ 10 5 1 \\le n, m\\le 10\^5 1≤n,m≤105, 1 ≤ a i ≤ 10 4 1 \\le a_i\\le 10\^4 1≤ai≤104。 #### 代码 ```java import java.util.*; import java.io.*; public class Main { public static void main(String[] args) throws IOException{ // TODO 自动生成的方法存根 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); int n=Integer.parseInt(br.readLine()); StringTokenizer st=new StringTokenizer(br.readLine()); int [] arr=new int[n]; for(int i=0;i0){ String []s=br.readLine().split(" "); int l=Integer.parseInt(s[0]); int r=Integer.parseInt(s[1]); System.out.println(pre[r]-pre[l-1]); } } } ``` ## B3693 数列前缀和 4 ### 题目背景 这次不是数列的问题了。 ### 题目描述 给定一个 n n n 行 m m m 列的矩阵 a a a,有 q q q 次询问,每次给定 ( u , v ) (u, v) (u,v) 和 ( x , y ) (x, y) (x,y),请你求出: ( ∑ i = u x ∑ j = v y a i , j )   m o d   2 64 (\\sum_{i = u}\^x \\sum_{j = v}\^y a_{i,j}) \\bmod 2\^{64} (i=u∑xj=v∑yai,j)mod264 也就是求出以 ( u , v ) (u, v) (u,v) 为左上角、 ( x , y ) (x,y) (x,y) 为右下角的矩形元素和对 2 64 2\^{64} 264 取余数的结果。 ### 输入格式 **本题单测试点内有多组测试数据**。 输入的第一行是一个整数 T T T,表示数据组数。接下来依次给出每组数据的输入信息: 第一行三个整数,依次表示矩阵的行数 n n n 和列数 m m m 以及询问数 q q q。 接下来 n n n 行,每行 m m m 个整数。第 i i i 行第 j j j 个整数表示 a i , j a_{i,j} ai,j。 接下来 q q q 行,每行四个整数,依次为 u , v , x , y u,v,x, y u,v,x,y,表示一组询问。 ### 输出格式 为了避免输出过大,对于每组数据,请输出一行一个整数,表示本组数据的所有询问的答案的按位异或和。 ### 输入输出样例 #1 #### 输入 #1 2 3 3 3 1 2 3 4 5 6 7 8 9 1 1 3 3 2 1 2 2 1 2 2 3 2 2 1 1 3 4 6 2 2 2 2 #### 输出 #1 52 6 ### 说明/提示 #### 样例 1 解释 对第一组数据,三次询问的答案依次为 45 , 9 , 16 45,9,16 45,9,16。其按位异或和为 52 52 52。 #### 数据规模与约定 对全部的测试点,保证 1 ≤ T ≤ 10 1 \\leq T \\leq 10 1≤T≤10, 1 ≤ n , m ≤ 10 3 1 \\leq n, m \\leq 10\^3 1≤n,m≤103, 1 ≤ q ≤ 10 6 1 \\leq q \\leq 10\^6 1≤q≤106, 0 ≤ a i \< 2 64 0 \\leq a_i \< 2\^{64} 0≤ai\<264, 1 ≤ u ≤ x ≤ n 1 \\leq u \\leq x \\leq n 1≤u≤x≤n, 1 ≤ v ≤ y ≤ m 1 \\leq v \\leq y \\leq m 1≤v≤y≤m。 数据保证 ∑ ( n × m ) ≤ 10 6 \\sum(n \\times m) \\leq 10\^6 ∑(n×m)≤106, ∑ q ≤ 10 6 \\sum q \\leq 10\^6 ∑q≤106。即输入矩阵的总大小和询问总数均不超过 10 6 10\^6 106。 #### 提示 如果你不知道什么是按位异或和,可以在你的代码里添加如下的函数: ```cpp template T getXorSum(T *begin, T *end) { T ret = 0; for (T *it = begin; it != end; ++it) ret ^= *it; return ret; } ``` 这一函数的作用是计算传入数组(包括 `std::vector`)某一左闭右开区间的按位异或和,返回值类型与传入数组的类型相同,调用方法与 `std::sort` 类似,例如,要求数组 a a a 的 a 1 ∼ a n a_1 \\sim a_n a1∼an 的按位异或和,则调用 `getXorSum(a + 1, a + 1 + n)`,求 a 0 ∼ a n − 1 a_0 \\sim a_{n - 1} a0∼an−1 的按位异或和,则调用 `getXorSum(a, a + n)`。如果 a a a 是 `std::vector`,则将上述调用代码里的 `a` 均改为 `a.begin()` 即可。 #### 代码 ```java import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws IOException { // TODO 自动生成的方法存根 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); int t=Integer.parseInt(br.readLine()); while(t-->0){ String [] s=br.readLine().split(" "); int n=Integer.parseInt(s[0]); int m=Integer.parseInt(s[1]); int q=Integer.parseInt(s[2]); long [][] pre=new long[n+1][m+1]; for(int i=1;i0){ String [] a=br.readLine().split(" "); int u=Integer.parseInt(a[0]); int v=Integer.parseInt(a[1]); int x=Integer.parseInt(a[2]); int y=Integer.parseInt(a[3]); long res=pre[x][y]-pre[u-1][y]-pre[x][v-1]+pre[u-1][v-1]; sum^=res; } bw.write(Long.toUnsignedString(sum)+"\n"); } bw.flush(); } } ``` > \[!NOTE

无符号输入:parseUnsignedLong()

无符号输出:Long.toUnsignedString()

P3131 [USACO16JAN] Subsequences Summing to Sevens S

题目描述

Farmer John 的 N N N 头奶牛站成一排,这是它们时不时会做的事情。每头奶牛都有一个独特的整数 ID 编号,以便 Farmer John 能够区分它们。Farmer John 希望为一组连续的奶牛拍照,但由于童年时与数字 1 ... 6 1 \ldots 6 1...6 相关的创伤事件,他只希望拍摄一组奶牛,如果它们的 ID 加起来是 7 7 7 的倍数。

请帮助 Farmer John 确定他可以拍摄的最大奶牛组的大小。

输入格式

输入的第一行包含 N N N( 1 ≤ N ≤ 50 , 000 1 \leq N \leq 50,000 1≤N≤50,000)。接下来的 N N N 行每行包含一头奶牛的整数 ID(所有 ID 都在 0 ... 1 , 000 , 000 0 \ldots 1,000,000 0...1,000,000 范围内)。

输出格式

请输出 ID 之和为 7 7 7 的倍数的最大连续奶牛组中的奶牛数量。如果不存在这样的组,则输出 0 0 0。

输入输出样例 #1

输入 #1

复制代码
7
3
5
1
6
2
14
10

输出 #1

复制代码
5

说明/提示

在这个例子中, 5 + 1 + 6 + 2 + 14 = 28 5+1+6+2+14 = 28 5+1+6+2+14=28。

代码

java 复制代码
import java.io.*;
import java.util.*;
public class Main {

	public static void main(String[] args) throws IOException{
		// TODO 自动生成的方法存根
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(br.readLine());
        long []pre=new long[n+1];
        int y;
        for(int i=1;i<=n;i++){
            y=Integer.parseInt(br.readLine());
            pre[i]=pre[i-1]+y;
        }
        int []first=new int[7];
      for(int i = 0; i < 7; i++){
    first[i] = -1;
}
        int max=0;
        first[0]=0;
        for(int i=1;i<=n;i++){
            int num=(int)(pre[i]%7);
            if(num<0){
                num+=7;
            }
            if(first[num]!=-1){
                max=Math.max(max,i-first[num]);
            }else{
                first[num]=i;
            }
        }
        System.out.print(max);
}
}

P8649 [蓝桥杯 2017 省 B] k 倍区间

题目描述

给定一个长度为 N N N 的数列, A 1 , A 2 , ⋯ A N A_1,A_2, \cdots A_N A1,A2,⋯AN,如果其中一段连续的子序列 A i , A i + 1 , ⋯ A j ( i ≤ j ) A_i,A_{i+1}, \cdots A_j(i \le j) Ai,Ai+1,⋯Aj(i≤j) 之和是 K K K 的倍数,我们就称这个区间 [ i , j ] [i,j] [i,j] 是 K K K 倍区间。

你能求出数列中总共有多少个 K K K 倍区间吗?

输入格式

第一行包含两个整数 N N N 和 K K K ( 1 ≤ N , K ≤ 10 5 ) (1 \le N,K \le 10^5) (1≤N,K≤105)。

以下 N N N 行每行包含一个整数 A i A_i Ai ( 1 ≤ A i ≤ 10 5 ) (1 \le A_i \le 10^5) (1≤Ai≤105)。

输出格式

输出一个整数,代表 K K K 倍区间的数目。

输入输出样例 #1

输入 #1

复制代码
5 2
1  
2  
3  
4  
5  

输出 #1

复制代码
6

说明/提示

时限 2 秒, 256M。蓝桥杯 2017 年第八届

代码

java 复制代码
import java.io.*;
import java.util.*;
public class Main {

	public static void main(String[] args) throws IOException{
		// TODO 自动生成的方法存根
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());
        int n=Integer.parseInt(st.nextToken());
        int k=Integer.parseInt(st.nextToken());
        long [] pre=new long [n+1];
        int num=0;
        for(int i=1;i<n+1;i++){
            num=Integer.parseInt(br.readLine());
            pre[i]=pre[i-1]+num;
        }
        long []first=new long[k];
        // for(int i=0;i<k;i++){
        //     first[i]=-1;
        // }
        first[0]=1L;
        long sum=0;
        for(int i=1;i<=n;i++){
            int b=(int)(pre[i]%k);
            if(b<0){
                b+=k;
            }
            first[b]+=1L;
        }
        for(int i=0;i<k;i++){
            sum+=first[i]*(first[i]-1)/2;
        }
        System.out.println(sum);
}
}

P1464 [PacNW 1999] Function

题目描述

对于一个递归函数 w ( a , b , c ) w(a,b,c) w(a,b,c)

  • 如果 a ≤ 0 a \le 0 a≤0 或 b ≤ 0 b \le 0 b≤0 或 c ≤ 0 c \le 0 c≤0 就返回值 1 1 1。
  • 如果 a > 20 a>20 a>20 或 b > 20 b>20 b>20 或 c > 20 c>20 c>20 就返回 w ( 20 , 20 , 20 ) w(20,20,20) w(20,20,20)
  • 如果 a < b a<b a<b 并且 b < c b<c b<c 就返回 w ( a , b , c − 1 ) + w ( a , b − 1 , c − 1 ) − w ( a , b − 1 , c ) w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c) w(a,b,c−1)+w(a,b−1,c−1)−w(a,b−1,c)。
  • 其它的情况就返回 w ( a − 1 , b , c ) + w ( a − 1 , b − 1 , c ) + w ( a − 1 , b , c − 1 ) − w ( a − 1 , b − 1 , c − 1 ) w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1) w(a−1,b,c)+w(a−1,b−1,c)+w(a−1,b,c−1)−w(a−1,b−1,c−1)

这是个简单的递归函数,但实现起来可能会有些问题。当 a , b , c a,b,c a,b,c 均为 15 15 15 时,调用的次数将非常的多。你要想个办法才行。

注意:例如 w ( 30 , − 1 , 0 ) w(30,-1,0) w(30,−1,0) 又满足条件 1 1 1 又满足条件 2 2 2,请按照最上面的条件来算,答案为 1 1 1。

输入格式

会有若干行。

并以 − 1 , − 1 , − 1 -1,-1,-1 −1,−1,−1 结束。

输出格式

输出若干行,每一行格式:

w(a, b, c) = ans

注意空格。

输入输出样例 #1

输入 #1

复制代码
1 1 1
2 2 2
-1 -1 -1

输出 #1

复制代码
w(1, 1, 1) = 2
w(2, 2, 2) = 4

说明/提示

数据规模与约定

保证输入的数在 [ − 9223372036854775808 , 9223372036854775807 ] [-9223372036854775808,9223372036854775807] [−9223372036854775808,9223372036854775807] 之间,并且是整数。

保证不包括 − 1 , − 1 , − 1 -1, -1, -1 −1,−1,−1 的输入行数 T T T 满足 1 ≤ T ≤ 10 5 1 \leq T \leq 10 ^ 5 1≤T≤105。

代码

java 复制代码
import java.io.*;
import java.util.*;
public class Main {
        static long[][][] dp = new long[25][25][25];
	public static void main(String[] args) throws IOException{
		// TODO 自动生成的方法存根
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
       
        while(true){
             StringTokenizer st=new StringTokenizer(br.readLine());
            long a=Long.parseLong(st.nextToken());
            long b=Long.parseLong(st.nextToken());
            long c=Long.parseLong(st.nextToken());
            if(a==-1&&b==-1&&c==-1){
                break;
            }
            long sum=w(a,b,c);
            System.out.println("w("+a+", "+b+", "+c+") = "+sum);
        }
}
    static public long w(long a,long b,long c){
      
    	int x=(int)a;
    	int y=(int)b;
    	int z=(int)c;
          
        if(a<=0||b<=0||c<=0){
            return 1;
        }else if(a>20||b>20||c>20){
            dp[20][20][20]=w(20, 20, 20);
            return dp[20][20][20];
        }else {
            if(a<b&&b<c) {
        	if(dp[x][y][z-1]==0) {
        		dp[x][y][z-1]= w(a, b, c-1);
        	} if(dp[x][y-1][z-1]==0) {
        		dp[x][y-1][z-1]= w(a, b-1, c-1);
        	} if(dp[x][y-1][z]==0) {
        		dp[x][y-1][z]= w(a, b-1, c);
        	}
        	dp[x][y][z]=dp[x][y][z-1]+dp[x][y-1][z-1]-dp[x][y-1][z];
        }else {
        	if(dp[x-1][y][z]==0) {
        		dp[x-1][y][z]= w(a-1, b, c);
        	} if(dp[x-1][y-1][z]==0) {
        		dp[x-1][y-1][z]= w(a-1, b-1, c);
        	} if(dp[x-1][y][z-1]==0) {
        		dp[x-1][y][z-1]= w(a-1, b, c-1);
        	} if(dp[x-1][y-1][z-1]==0) {
        		dp[x-1][y-1][z-1]= w(a-1, b-1, c-1);
        	}
        	dp[x][y][z]=dp[x-1][y][z]+dp[x-1][y-1][z]+dp[x-1][y][z-1]-dp[x-1][y-1][z-1];
        }
             return dp[x][y][z];
        }
       
    }
}

P2036 [COCI 2008/2009 #2] PERKET

题目描述

Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n n n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s s s 和苦度 b b b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。

众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。

另外,我们必须添加至少一种配料,因为没有任何食物是只以水为配料的。

输入格式

第一行一个整数 n n n,表示可供选用的食材种类数。

接下来 n n n 行,每行 2 2 2 个整数 s i s_i si 和 b i b_i bi,表示第 i i i 种食材的酸度和苦度。

输出格式

一行一个整数,表示可能的总酸度和总苦度的最小绝对差。

输入输出样例 #1

输入 #1

复制代码
1
3 10

输出 #1

复制代码
7

输入输出样例 #2

输入 #2

复制代码
2
3 8
5 8

输出 #2

复制代码
1

输入输出样例 #3

输入 #3

复制代码
4
1 7
2 6
3 8
4 9

输出 #3

复制代码
1

说明/提示

对于第三组样例,选择最后三种食材,此时的总酸度为 2 × 3 × 4 = 24 2 \times 3 \times 4 = 24 2×3×4=24,总苦度为 6 + 8 + 9 = 23 6+8+9=23 6+8+9=23,差值为 1 1 1。

数据规模与约定

对于 100 % 100\% 100% 的数据,有 1 ≤ n ≤ 10 1 \leq n \leq 10 1≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1 × 10 9 1 \times 10^9 1×109。

说明

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
	 static int []suan;
    static int []ku;
    static int min=Integer.MAX_VALUE;
    static int n;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
     n=Integer.parseInt(br.readLine());
    suan=new int[n+1];
    ku=new int[n+1];
    for(int i=1;i<=n;i++) {
    	StringTokenizer st=new StringTokenizer(br.readLine());
    	suan[i]=Integer.parseInt(st.nextToken());
    	ku[i]=Integer.parseInt(st.nextToken());
    }
    dfs(1, 1, 0);
    System.out.println(min);
}
static public void dfs(int i,int a,int b) {
	if(i>n) {
		if(a==1&&b==0) return;
		min=Math.min(min, Math.abs(a-b));
	
	}else {
		dfs(i+1, a, b);
		dfs(i+1, a*suan[i], b+ku[i]);
	}
}
}

P1101 单词方阵

题目描述

给一 n × n n \times n n×n 的字母方阵,内可能蕴含多个 yizhong 单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 8 8 8 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用 * 代替,以突出显示单词。

输入格式

第一行输入一个数 n n n。 ( 7 ≤ n ≤ 100 ) (7 \le n \le 100) (7≤n≤100)。

第二行开始输入 n × n n \times n n×n 的字母矩阵。

输出格式

突出显示单词的 n × n n \times n n×n 矩阵。

输入输出样例 #1

输入 #1

复制代码
7
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa

输出 #1

复制代码
*******
*******
*******
*******
*******
*******
*******

输入输出样例 #2

输入 #2

复制代码
8
qyizhong
gydthkjy
nwidghji
orbzsfgz
hhgrhwth
zzzzzozo
iwdfrgng
yyyygggg

输出 #2

复制代码
*yizhong
gy******
n*i*****
o**z****
h***h***
z****o**
i*****n*
y******g

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
	 // static int []dx={-1,-1,0,1,1,1,0,-1};
	 // static int []dy={0,1,1,1,0,-1,-1,-1};
    static int[] dx = {-1,-1,-1, 0,0, 1,1,1};
static int[] dy = {-1,0,1, -1,1, -1,0,1};
	 static String string="yizhong";
	static char [][]arr;
	static int n;
	static boolean [][]flag;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    n=Integer.parseInt(br.readLine());
    flag=new boolean[n+5][n+5];
    arr=new char[n+5][n+5];
  
    for(int i=0;i<n;i++) {
    	arr[i]=br.readLine().toCharArray();
    }
    for(int i=0;i<n;i++) {
    	for(int j=0;j<n;j++) {
    		if(arr[i][j]=='y') {
    			for(int k=0;k<8;k++) {
    				dfs(i,j,k,0);
    			}
    		}
    	}
    }
    for(int i=0;i<n;i++) {
    	for(int j=0;j<n;j++) {
    		if(flag[i][j]) {
    			System.out.print(arr[i][j]);
    		}
    		else {
    			System.out.print("*");
    		}
    	}
    	System.out.print("\n");
    }
}
static public boolean dfs(int i,int j,int k,int idx) {
	if(i<0||i>=n||j<0||j>=n) {
	return false;
	}

	if(arr[i][j]!=string.charAt(idx)) return false;
if(idx==6) {
	flag[i][j]=true;
	return true;
}
int ni=i+dx[k];
int nj=j+dy[k];

if(dfs(ni, nj, k, idx+1)){
    if(flag[ni][nj]) {
	flag[i][j]=true;
    return true;
}
}
return false;
}
}

P1162 填涂颜色

题目描述

由数字 0 0 0 组成的方阵中,有一任意形状的由数字 1 1 1 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 2 2 2。例如: 6 × 6 6\times 6 6×6 的方阵( n = 6 n=6 n=6),涂色前和涂色后的方阵如下:

如果从某个 0 0 0 出发,只向上下左右 4 4 4 个方向移动且仅经过其他 0 0 0 的情况下,无法到达方阵的边界,就认为这个 0 0 0 在闭合圈内 。闭合圈不一定是环形的,可以是任意形状,但保证闭合圈内 的 0 0 0 是连通的(两两之间可以相互到达)。

plain 复制代码
0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 1 0 1
1 1 1 1 1 1
plain 复制代码
0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 1 2 1
1 1 1 1 1 1

输入格式

每组测试数据第一行一个整数 n ( 1 ≤ n ≤ 30 ) n(1 \le n \le 30) n(1≤n≤30)。

接下来 n n n 行,由 0 0 0 和 1 1 1 组成的 n × n n \times n n×n 的方阵。

方阵内只有一个闭合圈,圈内至少有一个 0 0 0。

输出格式

已经填好数字 2 2 2 的完整方阵。

输入输出样例 #1

输入 #1

复制代码
6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1

输出 #1

复制代码
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1

说明/提示

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 30 1 \le n \le 30 1≤n≤30。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
	static int [][]arr;
	static int n;
	static int[]dx= {-1,0,1,0};
	static int[]dy= {0,1,0,-1};
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    n=Integer.parseInt(br.readLine());
    arr=new int[n+5][n+5];
    for(int i=0;i<n;i++) {
    	StringTokenizer st=new StringTokenizer(br.readLine());
    	for(int j=0;j<n;j++) {
    		arr[i][j]=Integer.parseInt(st.nextToken());
    	}
    }
    for(int i=0;i<n;i++) {
    	for(int j=0;j<n;j++) {
    		if((i==0||i==n-1||j==0||j==n-1)&&arr[i][j]==0) {
    			
    				dfs(i,j);
    			
    			
    		}
    	}
    }
    for(int i=0;i<n;i++) {
    	for(int j=0;j<n;j++) {
    		if(arr[i][j]==3) {
    			System.out.print(0+" ");
    		}else if(arr[i][j]==1) {
    			System.out.print(1+" ");
    		}else {
    			System.out.print(2+" ");
    		}
    	}
    	System.out.println();
    }
}
static public void dfs(int i,int j) {
	if(i<0||i>=n||j<0||j>=n) return;
	if(arr[i][j]==0) {
		arr[i][j]=3;
		for(int x=0;x<4;x++) {
			int ni=i+dx[x];
			int nj=j+dy[x];
			dfs(ni, nj);
		}
		
	}
}
}

P1135 奇怪的电梯

题目背景

感谢 @yummy 提供的一些数据。

题目描述

呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第 i i i 层楼( 1 ≤ i ≤ N 1 \le i \le N 1≤i≤N)上有一个数字 K i K_i Ki( 0 ≤ K i ≤ N 0 \le K_i \le N 0≤Ki≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如: 3 , 3 , 1 , 2 , 5 3, 3, 1, 2, 5 3,3,1,2,5 代表了 K i K_i Ki( K 1 = 3 K_1=3 K1=3, K 2 = 3 K_2=3 K2=3,......),从 1 1 1 楼开始。在 1 1 1 楼,按"上"可以到 4 4 4 楼,按"下"是不起作用的,因为没有 − 2 -2 −2 楼。那么,从 A A A 楼到 B B B 楼至少要按几次按钮呢?

输入格式

共二行。

第一行为三个用空格隔开的正整数,表示 N , A , B N, A, B N,A,B( 1 ≤ N ≤ 200 1 \le N \le 200 1≤N≤200, 1 ≤ A , B ≤ N 1 \le A, B \le N 1≤A,B≤N)。

第二行为 N N N 个用空格隔开的非负整数,表示 K i K_i Ki。

输出格式

一行,即最少按键次数,若无法到达,则输出 -1

输入输出样例 #1

输入 #1

复制代码
5 1 5
3 3 1 2 5

输出 #1

复制代码
3

说明/提示

对于 100 % 100 \% 100% 的数据, 1 ≤ N ≤ 200 1 \le N \le 200 1≤N≤200, 1 ≤ A , B ≤ N 1 \le A, B \le N 1≤A,B≤N, 0 ≤ K i ≤ N 0 \le K_i \le N 0≤Ki≤N。

本题共 16 16 16 个测试点,前 15 15 15 个每个测试点 6 6 6 分,最后一个测试点 10 10 10 分。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
    int n=Integer.parseInt(stringTokenizer.nextToken());
    int a=Integer.parseInt(stringTokenizer.nextToken());
    int b=Integer.parseInt(stringTokenizer.nextToken());
    stringTokenizer=new StringTokenizer(br.readLine());
    PrintWriter pw=new PrintWriter(System.out,true);
    int []k=new int[n+5];
    int []step=new int[n+5];
    for(int i=1;i<=n;i++) {
    	k[i]=Integer.parseInt(stringTokenizer.nextToken());
    }
    Queue<Integer> queue=new LinkedList<>();
    step[a]=0;
    queue.add(a);
    int []d= {1,-1};
    while(!queue.isEmpty()) {
    	int now=queue.poll();
    	if(now==b) {
    		pw.println(step[b]);
    		pw.close();
    		return;
    	}
    	for(int i:d) {
    		int next=now+k[now]*i;
    		if(next>=1&&next<=n&&step[next]==0) {
    			step[next]=step[now]+1;
    			queue.add(next);
    		}
    		
    	}
    }
    pw.println(-1);
    pw.close();
}
}

P9241 [蓝桥杯 2023 省 B] 飞机降落

题目描述

N N N 架飞机准备降落到某个只有一条跑道的机场。其中第 i i i 架飞机在 T i T_{i} Ti 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 D i D_{i} Di 个单位时间,即它最早可以于 T i T_{i} Ti 时刻开始降落,最晩可以于 T i + D i T_{i}+D_{i} Ti+Di 时刻开始降落。降落过程需要 L i L_{i} Li 个单位时间。

一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落。

请你判断 N N N 架飞机是否可以全部安全降落。

输入格式

输入包含多组数据。

第一行包含一个整数 T T T,代表测试数据的组数。

对于每组数据,第一行包含一个整数 N N N。

以下 N N N 行,每行包含三个整数 T i , D i , L i T_{i},D_{i},L_{i} Ti,Di,Li。

输出格式

对于每组数据,输出 YES 或者 NO,代表是否可以全部安全降落。

输入输出样例 #1

输入 #1

复制代码
2
3
0 100 10
10 10 10
0 2 20
3
0 10 20
10 10 20
20 10 20

输出 #1

复制代码
YES
NO

说明/提示

【样例说明】

对于第一组数据,可以安排第 3 架飞机于 0 时刻开始降落,20 时刻完成降落。安排第 2 架飞机于 20 时刻开始降落,30 时刻完成降落。安排第 1 架飞机于 30 时刻开始降落,40 时刻完成降落。

对于第二组数据,无论如何安排,都会有飞机不能及时降落。

【评测用例规模与约定】

对于 30 % 30 \% 30% 的数据, N ≤ 2 N \leq 2 N≤2。

对于 100 % 100 \% 100% 的数据, 1 ≤ T ≤ 10 1 \leq T \leq 10 1≤T≤10, 1 ≤ N ≤ 10 1 \leq N \leq 10 1≤N≤10, 0 ≤ T i , D i , L i ≤ 10 5 0 \leq T_{i},D_{i},L_{i} \leq 10^{5} 0≤Ti,Di,Li≤105。

蓝桥杯 2023 省赛 B 组 D 题。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
	static int [][]arr;
	static int n;
	static boolean []vis;
	static boolean ok;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    int t=Integer.parseInt(br.readLine());
    
    while(t-->0) {
    	 n=Integer.parseInt(br.readLine());
    	 vis=new boolean[n+2];
    	arr=new int[n+4][3];
    	for(int i=0;i<n;i++) {
    		StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
    		arr[i][0]=Integer.parseInt(stringTokenizer.nextToken());
    		arr[i][1]=Integer.parseInt(stringTokenizer.nextToken());
    		arr[i][2]=Integer.parseInt(stringTokenizer.nextToken());
    		
    	}
    	dfs(0, 0);
    	if(ok) System.out.println("YES");
    	else System.out.println("NO");
    	ok=false;
    }
}
static public void dfs(int a,int b) {
	if(b==n) {
		ok=true;
		return;
	}
	int now=a;
	for(int i=0;i<n;i++) {
		if(vis[i]) continue;
		int t=arr[i][0];
		int d=arr[i][1];
		int l=arr[i][2];
		int max=Math.max(now, t);
		if(max<=t+d) {
			vis[i]=true;
			dfs(max+l, b+1);
			vis[i]=false;
		}
	}
}
}

P1036 [NOIP 2002 普及组] 选数

题目描述

已知 n n n 个整数 x 1 , x 2 , ⋯   , x n x_1,x_2,\cdots,x_n x1,x2,⋯,xn,以及 1 1 1 个整数 k k k( k < n k<n k<n)。从 n n n 个整数中任选 k k k 个整数相加,可分别得到一系列的和。例如当 n = 4 n=4 n=4, k = 3 k=3 k=3, 4 4 4 个整数分别为 3 , 7 , 12 , 19 3,7,12,19 3,7,12,19 时,可得全部的组合与它们的和为:

3 + 7 + 12 = 22 3+7+12=22 3+7+12=22

3 + 7 + 19 = 29 3+7+19=29 3+7+19=29

7 + 12 + 19 = 38 7+12+19=38 7+12+19=38

3 + 12 + 19 = 34 3+12+19=34 3+12+19=34

现在,要求你计算出和为素数共有多少种。

例如上例,只有一种的和为素数: 3 + 7 + 19 = 29 3+7+19=29 3+7+19=29。

输入格式

第一行两个空格隔开的整数 n , k n,k n,k( 1 ≤ n ≤ 20 1 \le n \le 20 1≤n≤20, k < n k<n k<n)。

第二行 n n n 个整数,分别为 x 1 , x 2 , ⋯   , x n x_1,x_2,\cdots,x_n x1,x2,⋯,xn( 1 ≤ x i ≤ 5 × 10 6 1 \le x_i \le 5\times 10^6 1≤xi≤5×106)。

输出格式

输出一个整数,表示种类数。

输入输出样例 #1

输入 #1

复制代码
4 3
3 7 12 19

输出 #1

复制代码
1

说明/提示

【题目来源】

NOIP 2002 普及组第二题

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
	static int n,k,ans;
	static int []arr;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
     n=Integer.parseInt(stringTokenizer.nextToken());
    k=Integer.parseInt(stringTokenizer.nextToken());
    arr=new int[n+5];
    ans=0;
    stringTokenizer=new StringTokenizer(br.readLine());
    for(int i=0;i<n;i++) {
    	arr[i]=Integer.parseInt(stringTokenizer.nextToken());
    }
    dfs(0, 0,0);
    System.out.println(ans);
}
static public boolean isPrime(int a) {
	if(a<2) {
		return false;
	}
    if(a==2) return true;
    if(a%2==0) return false;
	for(int i=3;i*i<=a;i+=2) {
		if(a%i==0) return false;
	}
	return true;
}
static public void dfs(int a,int b,int sum) {
	if(b==k) {
		if(isPrime(sum)) ans++;
		return;
	}
    if (n - a < k - b) return;
	for(int i=a;i<n;i++) {
          b+=1;
        sum+=arr[i];
       
		dfs(i+1,b,sum);
		sum-=arr[i];
		b--;
	}
}
}

P1473 [USACO2.3] 零的数列 Zero Sum

题目描述

请考虑一个由 1 1 1 到 N N N 的数字组成的递增数列: 1 , 2 , 3 , ... , N 1, 2, 3, \ldots, N 1,2,3,...,N。

现在请在数列中插入 + 表示加,或者 - 表示减, (空格) 表示空白(例如 1-2 3 就等于 1-23),来将每一对数字组合在一起(请不要在第一个数字前插入符号)。

计算该表达式的结果并判断其值是否为 0 0 0。 请你写一个程序找出所有产生和为零的长度为N的数列。

输入格式

单独的一行表示整数 N N N( 3 ≤ N ≤ 9 3 \leq N \leq 9 3≤N≤9)。

输出格式

按照 ASCI I码的顺序,输出所有在每对数字间插入 +- (空格) 后能得到结果为零的数列。

输入输出样例 #1

输入 #1

复制代码
7

输出 #1

复制代码
1+2-3+4-5-6+7
1+2-3-4+5+6-7
1-2 3+4+5+6+7
1-2 3-4 5+6 7
1-2+3+4-5+6-7
1-2-3-4-5+6+7

说明/提示

翻译来自NOCOW

USACO 2.3

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
	static  int n;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    n=Integer.parseInt(br.readLine());
    dfs(2, 1, "1",1);
}
static public void dfs(int index,int sum,String s,int last) {
	if(index>n) {
		if(sum==0) {
			System.out.println(s);
		}
		return;
	}
	int newNum=last*10+(last>0?index:-index);
	dfs(index+1,sum-last+newNum,s+" "+index,newNum);
	dfs(index+1,sum+index,s+"+"+index,index);
	dfs(index+1,sum-index,s+"-"+index,-index);
}
}

P2040 打开所有的灯

题目背景

pmshz 在玩一个益 (ruo) 智 (zhi) 的小游戏,目的是打开九盏灯所有的灯,这样的游戏难倒了 pmshz......

题目描述

这个灯很奇 (fan) 怪 (ren),点一下就会将这个灯和其周围四盏灯的开关状态全部改变。现在你的任务就是就是告诉 pmshz 要全部打开这些灯。

例如

plain 复制代码
0  1  1
1  0  0
1  0  1

点一下最中间的灯 ( 2 , 2 ) (2,2) (2,2) 就变成了

plain 复制代码
0  0  1
0  1  1
1  1  1

再点一下左上角的灯 ( 1 , 1 ) (1,1) (1,1) 就变成了

plain 复制代码
1  1  1
1  1  1
1  1  1

达成目标。

最少需要 2 2 2 步。

输入格式

9 9 9 个数字,以 3 × 3 3\times3 3×3 的格式输入,每两个数字中间只有一个空格,表示灯初始的开关状态。( 0 0 0 表示关, 1 1 1 表示开)

输出格式

一个整数,表示最少打开所有灯所需要的步数。

输入输出样例 #1

输入 #1

复制代码
0 1 1
1 0 0
1 0 1

输出 #1

复制代码
2

说明/提示

这个题水不水,就看你怎么考虑了......

代码

java 复制代码
import java.util.*;
import java.util.zip.CheckedInputStream;
import java.io.*;
import java.security.spec.DSAGenParameterSpec;
public class Main {
	static int [][]arr=new int[5][5];
	static int min=Integer.MAX_VALUE;
	static int []dx= {-1,0,1,0,0};
	static int []dy= {0,1,0,-1,0};
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    for(int i=0;i<3;i++) {
    	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
    	arr[i][0]=Integer.parseInt(stringTokenizer.nextToken());
    	arr[i][1]=Integer.parseInt(stringTokenizer.nextToken());
    	arr[i][2]=Integer.parseInt(stringTokenizer.nextToken());
    }
    dfs(0, 0);
    System.out.println(min);
}
static public void dfs(int dex,int step) {
	if(step>=min) return;
	if(dex>=9) {
		if(checkIn()) {
			min=step;
		}
		return;
		}
	dfs(dex+1, step);
	flap(dex);
	dfs(dex+1, step+1);
	flap(dex);
}
static public boolean checkIn() {
	for(int i=0;i<3;i++) {
		for(int j=0;j<3;j++) {
			if(arr[i][j]==0) {
				return false;
			}
		}
	}
	return true;
}
static public void flap(int dex) {
	int x=dex/3;
	int y=dex%3;
	for(int i=0;i<5;i++) {
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0&&ny>=0&&nx<3&&ny<3) {
			arr[nx][ny]^=1;	
		}
		
	}
}
}

P1219 [USACO1.5] 八皇后 Checker Challenge

题目描述

一个如下的 6 × 6 6 \times 6 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 2 4 6 1 3 5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5 来描述,第 i i i 个数字表示在第 i i i 行的相应位置有一个棋子,如下:

行号 1 2 3 4 5 6 1\ 2\ 3\ 4\ 5\ 6 1 2 3 4 5 6

列号 2 4 6 1 3 5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。

并把它们以上面的序列方法输出,解按字典顺序排列。

请输出前 3 3 3 个解。最后一行是解的总个数。

输入格式

一行一个正整数 n n n,表示棋盘是 n × n n \times n n×n 大小的。

输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

输入输出样例 #1

输入 #1

复制代码
6

输出 #1

复制代码
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

说明/提示

【数据范围】

对于 100 % 100\% 100% 的数据, 6 ≤ n ≤ 13 6 \le n \le 13 6≤n≤13。

题目翻译来自NOCOW。

USACO Training Section 1.5

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
	static boolean []col;
	static boolean []dl;
	static boolean []dr;
	static int n,count=0;
	static int []ans;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    n=Integer.parseInt(br.readLine());
    col=new boolean[n+1];
    dl=new boolean[2*n+1];
    dr=new boolean[2*n+1];
    ans=new int[n+1];
   dfs(1);
   System.out.println(count);
}
static public void dfs(int row) {
	if(row>n) {
		count++;
		if(count<=3) {
			for(int i=1;i<=n;i++) {
				System.out.print(ans[i]+" ");
			}
			System.out.println();
		}
		return ;
	}
	for(int i=1;i<=n;i++) {
		int l=row-i+n;
		int r=row+i;
		if(!col[i]&&!dl[l]&&!dr[r]) {
			col[i]=true;
			dl[l]=true;
			dr[r]=true;
			ans[row]=i;
			dfs(row+1);
			col[i]=false;
			dl[l]=false;
			dr[r]=false;
			ans[row]=0;
		}
	}
}
}

B4158 [BCSP-X 2024 12 月小学高年级组] 质数补全

题目描述

Alice 在纸条上写了一个质数,第二天再看时发现有些地方污损看不清了。

  • 在大于 1 1 1 的自然数中,除了 1 1 1 和它本身以外不再有其他因数的自然数称为质数

请你帮助 Alice 补全这个质数,若有多解输出数值最小的,若无解输出 − 1 -1 −1。

例如纸条上的数字为 1 ∗ \tt{1*} 1∗( ∗ \tt{*} ∗ 代表看不清的地方),那么这个质数有可能为 11 , 13 , 17 , 19 11, 13, 17, 19 11,13,17,19,其中最小的为 11 11 11。

输入格式

第一行 1 1 1 个整数 t t t,代表有 t t t 组数据。

接下来 t t t 行,每行 1 1 1 个字符串 s s s 代表 Alice 的数字,仅包含数字或者 ∗ \tt{*} ∗,并且保证首位不是 ∗ \tt{*} ∗ 或者 0 0 0。

输出格式

输出 t t t 行,每行 1 1 1 个整数代表最小可能的质数,或者 − 1 -1 −1 代表无解。

输入输出样例 #1

输入 #1

复制代码
10
1*
3**
7**
83*7
2262
6**1
29*7
889*
777*
225*

输出 #1

复制代码
11
307
701
8317
-1
6011
2917
8893
-1
2251

输入输出样例 #2

输入 #2

复制代码
10
4039***
2***5*5
4099961
25**757
7***0**
1***00*
41811*9
6***0*7
8***1**
6561*59

输出 #2

复制代码
4039019
-1
4099961
2509757
7000003
1000003
4181129
6000047
8000101
6561259

说明/提示

样例 3-6

参考附件中的样例。

数据范围

∣ s ∣ |s| ∣s∣ 代表 s s s 串的长度,对于所有数据, 1 ≤ t ≤ 10 , 1 ≤ ∣ s ∣ ≤ 7 1 \leq t \leq 10, 1 \leq |s| \leq 7 1≤t≤10,1≤∣s∣≤7, s s s 中仅包含数字或者 ∗ \tt{*} ∗,并且保证首位不是 ∗ \tt{*} ∗ 或者 0 0 0。

本题采用捆绑测试,你必须通过子任务中的所有数据点以及其依赖的子任务,才能获得子任务对应的分数。

子任务编号 分值 ∣ s ∣ \mid s\mid ∣s∣ 特殊性质 子任务依赖
1 1 1 35 35 35 ≤ 7 \leq 7 ≤7 s s s 中没有 ∗ \tt{*} ∗
2 2 2 30 30 30 ≤ 4 \leq 4 ≤4
3 3 3 24 24 24 ≤ 7 \leq 7 ≤7 s s s 中至多包含 1 1 1 个 ∗ \tt{*} ∗ 1 1 1
4 4 4 11 11 11 ≤ 7 \leq 7 ≤7 1 , 2 , 3 1,2,3 1,2,3
java 复制代码
import java.util.*;
import java.io.*;
public class Main {
		static String s;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    int t=Integer.parseInt(br.readLine());
    while(t-->0) {
    	  s=br.readLine();
    	if(!dfs(0, 0L)) {
    		System.out.println(-1);
    	}
    	
    	
    }
}
static public boolean isPrime(long n) {
	if(n<2)  return false;
	if(n==2)  return true;
	if(n%2==0)  return false;
	for(int i=3;i*i<=n;i+=2) {
		if(n%i==0) return false;
	}
	return true;
}
static public boolean dfs(int i,long n) {
	if(i>=s.length()) {
		if(isPrime(n)) {
			System.out.println(n);
			return true;
		}
		return false;
	}

		if(s.charAt(i)=='*') {
			for(int j=0;j<=9;j++) {
				n=n*10+j;
				if(dfs(i+1, n)) {
					return true;
				}else {
					n=(n-j)/10;
				}
				
				
			}	
		}else {
			n=n*10+(s.charAt(i)-'0');
			if(dfs(i+1, n)) {
				return true;
			}else {
				n=(n-s.charAt(i))/10;
			}
			
		}
	
	return false;
}
}

P10386 [蓝桥杯 2024 省 A] 五子棋对弈

题目描述

"在五子棋的对弈中,友谊的小船说翻就翻?" 不!对小蓝和小桥来说,五子棋不仅是棋盘上的较量,更是心与心之间的沟通。这两位挚友秉承着 "友谊第一,比赛第二" 的宗旨,决定在一块 5 × 5 5 × 5 5×5 的棋盘上,用黑白两色的棋子来决出胜负。但他们又都不忍心让对方失落,于是决定用一场和棋(平局) 作为彼此友谊的见证。

比赛遵循以下规则:

  1. 棋盘规模:比赛在一个 5 × 5 5 × 5 5×5 的方格棋盘上进行,共有 25 25 25 个格子供下棋使用。
  2. 棋子类型:两种棋子,黑棋与白棋,代表双方。小蓝持白棋,小桥持黑棋。
  3. 先手规则:白棋(小蓝)具有先手优势,即在棋盘空白时率先落子(下棋)。
  4. 轮流落子:玩家们交替在棋盘上放置各自的棋子,每次仅放置一枚。
  5. 胜利条件:率先在横线、竖线或斜线上形成连续的五个同色棋子的一方获胜。
  6. 平局条件:当所有 25 25 25 个棋盘格都被下满棋子,而未决出胜负时,游戏以平局告终。

在这一设定下,小蓝和小桥想知道,有多少种不同的棋局情况(终局不同看成不同情况,终局相同而落子顺序不同看成同一种情况),既确保棋盘下满又保证比赛结果为平局。

输入格式

这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

输出格式

这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

代码

java 复制代码
package text;

import java.util.*;
import java.io.*;
public class test1 {
		static int [][]arr=new int[6][6];
		static int count=0;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
    dfs(0, 0, 0);
    System.out.println(count);
    
}

static public void dfs(int index,int white,int black) {
	if(index>=25) {
		if(white==13&&black==12) {
			if(check()) {
				count++;
			}
		}
		return;
	}
	int x=index/5;
	int y=index%5;
	arr[x][y]=0;
	dfs(index+1,white+1,black);
	arr[x][y]=1;
	dfs(index+1,white,black+1);
}
static public boolean check() {
	for(int i=0;i<5;i++) {
		if(arr[i][0]==arr[i][1]&&arr[i][2]==arr[i][1]&&arr[i][2]==arr[i][3]&&arr[i][3]==arr[i][4]) {
			return false;
		}
	}
	for(int i=0;i<5;i++) {
		if(arr[0][i]==arr[1][i]&&arr[2][i]==arr[1][i]&&arr[2][i]==arr[3][i]&&arr[3][i]==arr[4][i]) {
			return false;
		}
	}
	
		if(arr[0][0]==arr[1][1]&&arr[2][2]==arr[1][1]&&arr[2][2]==arr[3][3]&&arr[3][3]==arr[4][4]) {
			return false;
		}
		if(arr[0][4]==arr[1][3]&&arr[2][2]==arr[1][3]&&arr[2][2]==arr[3][1]&&arr[3][1]==arr[4][0]) {
			return false;
		}
	return true;
}
}

P8786 [蓝桥杯 2022 省 B] 李白打酒加强版

题目描述

话说大诗人李白,一生好饮。幸好他从不开车。

一天,他提着酒壶,从家里出来,酒壶中有酒 2 2 2 斗。他边走边唱:

无事街上走,提壶去打酒。

逢店加一倍,遇花喝一斗。

这一路上,他一共遇到店 N N N 次,遇到花 M M M 次。已知最后一次遇到的是花,他正好把酒喝光了。

请你计算李白这一路遇到店和花的顺序,有多少种不同的可能?

注意:壶里没酒( 0 0 0 斗)时遇店是合法的,加倍后还是没酒;但是没酒时遇花是不合法的。

输入格式

第一行包含两个整数 N N N 和 M M M。

输出格式

输出一个整数表示答案。由于答案可能很大,输出模 1000000007 1000000007 1000000007(即 10 9 + 7 10^9+7 109+7)的结果。

输入输出样例 #1

输入 #1

复制代码
5 10

输出 #1

复制代码
14

说明/提示

【样例说明】

如果我们用 0 代表遇到花,1 代表遇到店, 14 14 14 种顺序如下:

plain 复制代码
010101101000000
010110010010000
011000110010000
100010110010000
011001000110000
100011000110000
100100010110000
010110100000100
011001001000100
100011001000100
100100011000100
011010000010100
100100100010100
101000001010100

【评测用例规模与约定】

对于 40 % 40 \% 40% 的评测用例: 1 ≤ N , M ≤ 10 1 \leq N, M \leq 10 1≤N,M≤10。

对于 100 % 100 \% 100% 的评测用例: 1 ≤ N , M ≤ 100 1 \leq N, M \leq 100 1≤N,M≤100。

蓝桥杯 2022 省赛 B 组 I 题。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	int n=Integer.parseInt(stringTokenizer.nextToken());
	int m=Integer.parseInt(stringTokenizer.nextToken());
	int [][][]dp=new int[n+5][m+5][105];
	dp[0][0][2]=1;
	for(int i=0;i<=n;i++) {
		for(int j=0;j<=m-1;j++) {
			if(i==0&&j==0) continue;
			for(int k=0;k<=100;k++) {
				if(k%2==0&&i!=0) dp[i][j][k]+=dp[i-1][j][k/2];
				if(j!=0)dp[i][j][k]+=dp[i][j-1][k+1];
				dp[i][j][k]%=1000000007;
			}
		}
	}
	System.out.println(dp[n][m-1][1]);
}
}

P12344 [蓝桥杯 2025 省 B/Python B 第二场] 破解信息

题目描述

在遥远的未来,星际旅行已经成为常态。宇航员小蓝在一次探险任务中,意外发现了一个古老的太空遗迹。遗迹中存放着一个数据存储器,里面记录着一段加密的信息。经过初步分析,小蓝发现这段信息可以被表示为一个字符串 S S S,而解密的关键,在于找出 S S S 中字典序最大的回文子序列。

  • 子序列 :指从原字符串中抽取若干个字符(可以不连续),按照它们在原字符串中的相对顺序排列所形成的新序列。例如,对于字符串 abc,其子序列包括 abcabacbcabc
  • 字典序 :指字符串按照字典中的排序规则比较大小的方式。对于两个字符串,从左到右逐字符比较,先出现较大字符的字符串字典序更大;若比较到某个字符串结束仍未找到不同的字符,则较短的字符串字典序较小。例如,abc < abd,而 ab < abc

现在,请你从字符串 S S S 中,找出字典序最大的回文子序列,帮助小蓝解开这段来自星际文明的信息。

输入格式

输入一行包含一个字符串 S S S,表示加密的信息。

输出格式

输出一行包含一个字符串,表示 S S S 中字典序最大的回文子序列。

输入输出样例 #1

输入 #1

复制代码
abcd

输出 #1

复制代码
d

输入输出样例 #2

输入 #2

复制代码
abab

输出 #2

复制代码
bb

说明/提示

评测用例规模与约定

  • 对于 30 % 30\% 30% 的评测用例, 1 ≤ ∣ S ∣ ≤ 300 1 \leq |S| \leq 300 1≤∣S∣≤300,其中 ∣ S ∣ |S| ∣S∣ 表示字符串 S S S 的长度;
  • 对于所有评测用例, 1 ≤ ∣ S ∣ ≤ 10 5 1 \leq |S| \leq 10^5 1≤∣S∣≤105, S S S 中只包含小写英文字母。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	String strings=br.readLine();
	char max='a';
	for(int i=0;i<strings.length();i++) {
		if(strings.charAt(i)>max) {
			max=strings.charAt(i);
		}
	}
	StringBuilder stringBuilder=new StringBuilder();
	for(int i=0;i<strings.length();i++) {
		if(strings.charAt(i)==max) {
			stringBuilder.append(max);
		}
	}
	System.out.println(stringBuilder);
}
}

P12342 [蓝桥杯 2025 省 B/Python B 第二场] 数列差分

题目描述

小蓝有两个长度均为 n n n 的数列 A = { a 1 , a 2 , ⋯   , a n } A=\{a_1, a_2, \cdots, a_n\} A={a1,a2,⋯,an} 和 B = { b 1 , b 2 , ⋯   , b n } B=\{b_1, b_2, \cdots, b_n\} B={b1,b2,⋯,bn},将两个数列作差定义为 C = A − B = { c 1 = a 1 − b 1 , c 2 = a 2 − b 2 , ⋯   , c n = a n − b n } C=A-B=\{c_1=a_1-b_1, c_2=a_2-b_2, \cdots, c_n=a_n-b_n\} C=A−B={c1=a1−b1,c2=a2−b2,⋯,cn=an−bn}。小蓝将对数列 B B B 进行若干次操作,每次操作可以将数列 B B B 中的任意一个数更改为任意一个整数。在进行完所有操作后,小蓝可以按任意顺序将数列 B B B 重排,之后再计算数列 C C C。小蓝想知道,最少操作多少次可以使得数列 C C C 中的所有数都为正整数。

输入格式

输入的第一行包含一个正整数 n n n;

第二行包含 n n n 个整数 a 1 , a 2 , ⋯   , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an,相邻整数之间使用一个空格分隔。

第三行包含 n n n 个整数 b 1 , b 2 , ⋯   , b n b_1, b_2, \cdots, b_n b1,b2,⋯,bn,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示答案。

输入输出样例 #1

输入 #1

复制代码
4
22 31 12 14
3 19 27 44

输出 #1

复制代码
1

说明/提示

样例说明

其中一种方案:将 44 44 44 改为 0 0 0,重新排列 B B B 为 { 19 , 27 , 3 , 0 } \{19, 27, 3, 0\} {19,27,3,0},使得数列 C = { 3 , 4 , 9 , 14 } C=\{3, 4, 9, 14\} C={3,4,9,14} 均为正整数。

评测用例规模与约定

  • 对于 30 % 30\% 30% 的评测用例, n ≤ 10 n \leq 10 n≤10;
  • 对于所有评测用例, 1 ≤ n ≤ 10 5 1 \leq n \leq 10^5 1≤n≤105, − 10 9 ≤ a i ≤ 10 9 -10^9 \leq a_i \leq 10^9 −109≤ai≤109, − 10 9 ≤ b i ≤ 10 9 -10^9 \leq b_i \leq 10^9 −109≤bi≤109。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	int n=Integer.parseInt(br.readLine());
	int []a=new int[n];
	int []b=new int[n];
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	for(int i=0;i<n;i++) {
		a[i]=Integer.parseInt(stringTokenizer.nextToken());
	}
	stringTokenizer=new StringTokenizer(br.readLine());
	for(int i=0;i<n;i++) {
		b[i]=Integer.parseInt(stringTokenizer.nextToken());
	}  
	int i=0;
	int j=0;
	int count=0;
	Arrays.sort(a);
	Arrays.sort(b);
	while(i<n&&j<n) {
		if(a[i]>b[j]) {
			i++;
			j++;
		}else {
			i++;
			count++;
		}
	}
	System.out.println(count);
}
}

二维数组排序

想按照第一列的顺序进行排序就[0],否则的话按照第二列就[1],如果是从小到大的话就(o1, o2) ->o1 - o2),反之,则从大到小

P9242 [蓝桥杯 2023 省 B] 接龙数列

题目描述

对于一个长度为 K K K 的整数数列: A 1 , A 2 , ... , A K A_{1},A_{2},\ldots,A_{K} A1,A2,...,AK,我们称之为接龙数列当且仅当 A i A_{i} Ai 的首位数字恰好等于 A i − 1 A_{i-1} Ai−1 的末位数字( 2 ≤ i ≤ K 2 \leq i \leq K 2≤i≤K)。

例如 12 , 23 , 35 , 56 , 61 , 11 12,23,35,56,61,11 12,23,35,56,61,11 是接龙数列; 12 , 23 , 34 , 56 12,23,34,56 12,23,34,56 不是接龙数列,因为 56 56 56 的首位数字不等于 34 34 34 的末位数字。所有长度为 1 1 1 的整数数列都是接龙数列。

现在给定一个长度为 N N N 的数列 A 1 , A 2 , ... , A N A_{1},A_{2},\ldots,A_{N} A1,A2,...,AN,请你计算最少从中删除多少 个数,可以使剩下的序列是接龙序列?

输入格式

第一行包含一个整数 N N N。

第二行包含 N N N 个整数 A 1 , A 2 , ... , A N A_{1},A_{2},\ldots,A_{N} A1,A2,...,AN。

输出格式

一个整数代表答案。

输入输出样例 #1

输入 #1

复制代码
5
11 121 22 12 2023

输出 #1

复制代码
1

说明/提示

【样例说明】

删除 22 22 22,剩余 11 , 121 , 12 , 2023 11,121,12,2023 11,121,12,2023 是接龙数列。

【评测用例规模与约定】

对于 20 % 20 \% 20% 的数据, 1 ≤ N ≤ 20 1 \leq N \leq 20 1≤N≤20。

对于 50 % 50 \% 50% 的数据, 1 ≤ N ≤ 10 4 1 \leq N \leq 10^4 1≤N≤104。

对于 100 % 100 \% 100% 的数据, 1 ≤ N ≤ 10 5 1 \leq N \leq 10^{5} 1≤N≤105, 1 ≤ A i ≤ 10 9 1 \leq A_{i} \leq 10^{9} 1≤Ai≤109。所有 A i A_{i} Ai 保证不包含前导 0。

蓝桥杯 2023 省赛 B 组 E 题。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	int n=Integer.parseInt(br.readLine());
	int []a=new int[n];
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	for(int i=0;i<n;i++) {
		a[i]=Integer.parseInt(stringTokenizer.nextToken());
	}
	int []dp=new int[10];
	for(int i=0;i<n;i++) {
		int first=a[i];
		while(first>=10) {
			first/=10;
		}
		int last=a[i]%10;
		dp[last]=Math.max(dp[last], dp[first]+1);
	}
	int max=Integer.MIN_VALUE;
	for(int i=0;i<10;i++) {
		max=Math.max(max, dp[i]);
	}
	System.out.println(n-max);
}
}

P10387 [蓝桥杯 2024 省 A] 训练士兵

题目描述

在蓝桥王国中,有 n n n 名士兵,这些士兵需要接受一系列特殊的训练,以提升他们的战斗技能。对于第 i i i 名士兵来说,进行一次训练所需的成本为 p i p_i pi 枚金币,而要想成为顶尖战士,他至少需要进行 c i c_i ci 次训练。

为了确保训练的高效性,王国推出了一种组团训练的方案。该方案包含每位士兵所需的一次训练,且总共只需支付 S S S 枚金币(组团训练方案可以多次购买,即士兵可以进行多次组团训练)。

作为训练指挥官,请你计算出最少需要花费多少金币,才能使得所有的士兵都成为顶尖战士?

输入格式

输入的第一行包含两个整数 n n n 和 S ,用一个空格分隔,表示士兵的数量和进行一次组团训练所需的金币数。

接下来的 n n n 行,每行包含两个整数 p i p_i pi 和 c i c_i ci,用一个空格分隔,表示第 i i i 名士兵进行一次训练的金币成本和要成为顶尖战士所需的训练次数。

输出格式

输出一行包含一个整数,表示使所有士兵成为顶尖战士所需的最少金币数。

输入输出样例 #1

输入 #1

复制代码
3 6
5 2
2 4
3 2

输出 #1

复制代码
16

说明/提示

花费金币最少的训练方式为:进行 2 2 2 次组团训练,花费 2 × 6 = 12 2 × 6 = 12 2×6=12 枚金币,此时士兵 1 , 3 1, 3 1,3 已成为顶尖战士;再花费 4 4 4 枚金币,让士兵 2 2 2 进行两次训练,成为顶尖战士。总花费为 12 + 4 = 16 12 + 4 = 16 12+4=16。

对于 40 % 40\% 40% 的评测用例, 1 ≤ n ≤ 10 3 , 1 ≤ p i , c i ≤ 10 5 , 1 ≤ S ≤ 10 7 1 ≤ n ≤ 10^3,1 ≤ p_i , c_i ≤ 10^5,1 ≤ S ≤ 10^7 1≤n≤103,1≤pi,ci≤105,1≤S≤107。

对于所有评测用例, 1 ≤ n ≤ 10 5 , 1 ≤ p i , c i ≤ 10 6 , 1 ≤ S ≤ 10 10 1 ≤ n ≤ 10^5,1 ≤ p_i , c_i ≤ 10^6,1 ≤ S ≤ 10^{10} 1≤n≤105,1≤pi,ci≤106,1≤S≤1010。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	int n=Integer.parseInt(stringTokenizer.nextToken());
	long s=Long.parseLong(stringTokenizer.nextToken());
	int [][]a=new int[n][2];
	int max=Integer.MIN_VALUE;
	long sum=0;
	for(int i=0;i<n;i++) {
		stringTokenizer=new StringTokenizer(br.readLine());
		a[i][0]=Integer.parseInt(stringTokenizer.nextToken());
		a[i][1]=Integer.parseInt(stringTokenizer.nextToken());
		max=Math.max(max, a[i][1]);
		sum+=(long)a[i][0];
	}
	Arrays.sort(a,(o1,o2)->o1[1]-o2[1]);
	int ji=0;
	long m=0;
	for(int i=0;i<n;i++) {
		if(sum>s) {
			ji=a[i][1];
			sum-=a[i][0];
			continue;
		}
		m+=(long)a[i][0]*(a[i][1]-ji);
	}
    m+=s*ji;
	System.out.println(m);
}
}

P1182 数列分段 Section II

题目描述

对于给定的一个长度为 N N N 的正整数数列 A 1 ∼ N A_{1\sim N} A1∼N,现要将其分成 M M M( M ≤ N M\leq N M≤N)段,并要求每段连续,且每段和的最大值最小。

关于最大值最小:

例如一数列 4 2 4 5 1 4\ 2\ 4\ 5\ 1 4 2 4 5 1 要分成 3 3 3 段。

将其如下分段:

4 2 \] \[ 4 5 \] \[ 1 \] \[4\\ 2\]\[4\\ 5\]\[1\] \[4 2\]\[4 5\]\[1

第一段和为 6 6 6,第 2 2 2 段和为 9 9 9,第 3 3 3 段和为 1 1 1,和最大值为 9 9 9。

将其如下分段:

4 \] \[ 2 4 \] \[ 5 1 \] \[4\]\[2\\ 4\]\[5\\ 1\] \[4\]\[2 4\]\[5 1

第一段和为 4 4 4,第 2 2 2 段和为 6 6 6,第 3 3 3 段和为 6 6 6,和最大值为 6 6 6。

并且无论如何分段,最大值不会小于 6 6 6。

所以可以得到要将数列 4 2 4 5 1 4\ 2\ 4\ 5\ 1 4 2 4 5 1 要分成 3 3 3 段,每段和的最大值最小为 6 6 6。

输入格式

第 1 1 1 行包含两个正整数 N , M N,M N,M。

第 2 2 2 行包含 N N N 个空格隔开的非负整数 A i A_i Ai,含义如题目所述。

输出格式

一个正整数,即每段和最大值最小为多少。

输入输出样例 #1

输入 #1

复制代码
5 3
4 2 4 5 1

输出 #1

复制代码
6

说明/提示

对于 20 % 20\% 20% 的数据, N ≤ 10 N\leq 10 N≤10。

对于 40 % 40\% 40% 的数据, N ≤ 1000 N\leq 1000 N≤1000。

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 10 5 1\leq N\leq 10^5 1≤N≤105, M ≤ N M\leq N M≤N, A i < 10 8 A_i < 10^8 Ai<108, 答案不超过 10 9 10^9 109。

代码

java 复制代码
import java.util.*;
import java.util.zip.CheckedInputStream;
import java.io.*;
public class Main {
	static int m;
	static int []a;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	int n=Integer.parseInt(stringTokenizer.nextToken());
	 m=Integer.parseInt(stringTokenizer.nextToken());
	a=new int[n];
	long right=0;
	long left=Integer.MIN_VALUE;
	long ans=0;
	stringTokenizer=new StringTokenizer(br.readLine());
	for(int i=0;i<n;i++) {
		a[i]=Integer.parseInt(stringTokenizer.nextToken());
		left=Math.max(left, a[i]);
		right+=a[i];
	}
	while(left<=right) {
		long mid=(left+right)/2;
		if(check(mid)) {
			ans=mid;
			right=mid-1;
		}else {
			left=mid+1;
		}
	}
	System.out.println(ans);
}
static boolean  check(long mid) {
	int sum=0;
	int count=1;
	for(int num:a) {
		if(sum+num>mid) {
			sum=num;
			count++;
			if(count>m) {
				return false;
			}
		}else {
			sum+=num;
		}
	}
	return count<=m;
}
}

P2440 木材加工

题目背景

要保护环境。

题目描述

木材厂有 n n n 根原木,现在想把这些木头切割成 k k k 段长度 为 l l l 的小段木头(木头有可能有剩余)。

当然,我们希望得到的小段木头越长越好,请求出 l l l 的最大值。

木头长度的单位是 cm \text{cm} cm,原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数。

例如有两根原木长度分别为 11 11 11 和 21 21 21,要求切割成等长的 6 6 6 段,很明显能切割出来的小段木头长度最长为 5 5 5。

输入格式

第一行是两个正整数 n , k n,k n,k,分别表示原木的数量,需要得到的小段的数量。

接下来 n n n 行,每行一个正整数 L i L_i Li,表示一根原木的长度。

输出格式

仅一行,即 l l l 的最大值。

如果连 1cm \text{1cm} 1cm 长的小段都切不出来,输出 0

输入输出样例 #1

输入 #1

复制代码
3 7
232
124
456

输出 #1

复制代码
114

说明/提示

数据规模与约定

对于 100 % 100\% 100% 的数据,有 1 ≤ n ≤ 10 5 1\le n\le 10^5 1≤n≤105, 1 ≤ k ≤ 10 8 1\le k\le 10^8 1≤k≤108, 1 ≤ L i ≤ 10 8 ( i ∈ [ 1 , n ] ) 1\le L_i\le 10^8(i\in[1,n]) 1≤Li≤108(i∈[1,n])。

代码

java 复制代码
import java.util.*;
import java.util.zip.CheckedInputStream;
import java.io.*;
public class Main {
	static int k,n;
	static int []a;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	 n=Integer.parseInt(stringTokenizer.nextToken());
	 k=Integer.parseInt(stringTokenizer.nextToken());
	a=new int[n+5];
	int right=1;
	for(int i=0;i<n;i++) {
		a[i]=Integer.parseInt(br.readLine());
		right=Math.max(right, a[i]);
	}
	int left=1;
	int ans=0;
	while(left<=right) {
		int mid=(left+right)/2;
		if(check(mid)) {
			right=mid-1;
			
		}else {
			left=mid+1;
            ans=mid;
		}
	}
	System.out.println(ans);
}
static boolean  check(long mid) {
	long count=0;
	for(int i:a) {
		count+=((long)i/mid);
		if(count >=k) return false;
	}
	return count<k;
}
}

P10909 [蓝桥杯 2024 国 B] 立定跳远

题目描述

在运动会上,小明从数轴的原点开始向正方向立定跳远。项目设置了 n n n 个检查点 a 1 , a 2 , ⋯   , a n a_1, a_2, \cdots , a_n a1,a2,⋯,an 且 a i ≥ a i − 1 > 0 a_i \ge a_{i−1} > 0 ai≥ai−1>0。小明必须先后跳跃到每个检查点上且只能跳跃到检查点上。同时,小明可以自行再增加 m m m 个检查点让自己跳得更轻松。

在运动会前,小明制定训练计划让自己单次跳跃的最远距离达到 L L L,并且学会一个爆发技能可以在运动会时使用一次,使用时可以在该次跳跃时的最远距离变为 2 L 2L 2L。小明想知道, L L L 的最小值是多少可以完成这个项目?

输入格式

输入共 2 2 2 行。

第一行为两个正整数 n , m n,m n,m。

第二行为 n n n 个由空格分开的正整数 a 1 , a 2 , ⋯   , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an。

输出格式

输出共 1 1 1 行,一个整数表示答案。

输入输出样例 #1

输入 #1

复制代码
5 3
1 3 5 16 21

输出 #1

复制代码
3

说明/提示

【样例说明】

增加检查点 10 , 13 , 19 10, 13, 19 10,13,19,因此每次跳跃距离为 1 , 2 , 2 , 5 , 3 , 3 , 3 , 2 1,2, 2, 5, 3, 3, 3, 2 1,2,2,5,3,3,3,2,在第三次跳跃时使用技能即可。

【评测用例规模与约定】

对于 20 % 20\% 20% 的评测用例,保证 n ≤ 10 2 n \le 10^2 n≤102, m ≤ 10 3 m \le 10^3 m≤103, a i ≤ 10 3 a_i \le 10^3 ai≤103。

对于 100 % 100\% 100% 的评测用例,保证 2 ≤ n ≤ 10 5 2 \le n \le 10^5 2≤n≤105, m ≤ 10 8 m \le 10^8 m≤108, 0 < a i ≤ 10 8 0 < a_i \le 10^8 0<ai≤108。

代码

java 复制代码
import java.util.*;
import java.io.*;
public class Main {
	static int m,n;
	static int []a;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	 n=Integer.parseInt(stringTokenizer.nextToken());
	 m=Integer.parseInt(stringTokenizer.nextToken());
	a=new int[n+5];
	stringTokenizer=new StringTokenizer(br.readLine());
	int max=0;
	int min=0;
	for(int i=0;i<n;i++) {
		a[i]=Integer.parseInt(stringTokenizer.nextToken());
		max=Math.max(max,a[i]);
		min=Math.min(min,a[i]);
	}
	long right=((long)max+min+1)/2;
	long left=0;
	long ans=0;
	while(left<=right) {
		long mid=(left+right)/2;
		if(check(mid)) {
			right=mid-1;
			ans=mid;
		}else {
			left=mid+1;
		}
	}
	System.out.println(ans);
}
static boolean  check(long mid) {
    boolean used=false;
    long count=0;
    int pos=0;
	for(int i=0;i<n;i++){
         if(pos+mid>=a[i]){
             pos=a[i];
             continue;
        }else if(pos+mid*2>=a[i]&&!used){
             used=true;
             pos=a[i];
             continue;
        }
        count++;
        if(count>m) return false;
        pos+=mid;
        i--;
    }
   return true;
}
}

P1048 [NOIP 2005 普及组] 采药

题目描述

辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:"孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。"

如果你是辰辰,你能完成这个任务吗?

输入格式

第一行有 2 2 2 个整数 T T T( 1 ≤ T ≤ 1000 1 \le T \le 1000 1≤T≤1000)和 M M M( 1 ≤ M ≤ 100 1 \le M \le 100 1≤M≤100),用一个空格隔开, T T T 代表总共能够用来采药的时间, M M M 代表山洞里的草药的数目。

接下来的 M M M 行每行包括两个在 1 1 1 到 100 100 100 之间(包括 1 1 1 和 100 100 100)的整数,分别表示采摘某株草药的时间和这株草药的价值。

输出格式

输出在规定的时间内可以采到的草药的最大总价值。

输入输出样例 #1

输入 #1

复制代码
70 3
71 100
69 1
1 2

输出 #1

复制代码
3

说明/提示

【数据范围】

  • 对于 30 % 30\% 30% 的数据, M ≤ 10 M \le 10 M≤10;
  • 对于全部的数据, M ≤ 100 M \le 100 M≤100。

【题目来源】

NOIP 2005 普及组第三题

代码(二维)

java 复制代码
import java.util.*;
import java.util.zip.CheckedInputStream;
import java.io.*;
public class Main {
	static int t,m;
	static int []ti;
	static int []vi;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	 t=Integer.parseInt(stringTokenizer.nextToken());
	 m=Integer.parseInt(stringTokenizer.nextToken());
	ti=new int[m+5];
	vi=new int[m+5];
	for(int i=1;i<=m;i++) {
		stringTokenizer=new StringTokenizer(br.readLine());
		ti[i]=Integer.parseInt(stringTokenizer.nextToken());
		vi[i]=Integer.parseInt(stringTokenizer.nextToken());
	}
	int [][]dp=new int[m+5][t+5];
	for(int i=1;i<=m;i++) {
		for(int j=0;j<=t;j++) {
			dp[i][j]=dp[i-1][j];
			if(j>=ti[i]) {
				dp[i][j]=Math.max(dp[i][j],dp[i-1][j-ti[i]]+vi[i]);
			}
		}
	}
	System.out.println(dp[m][t]);
}
}

代码(一维)

java 复制代码
import java.util.*;
import java.util.zip.CheckedInputStream;
import java.io.*;
public class Main {
	static int t,m;
	static int []ti;
	static int []vi;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	 t=Integer.parseInt(stringTokenizer.nextToken());
	 m=Integer.parseInt(stringTokenizer.nextToken());
	ti=new int[m+5];
	vi=new int[m+5];
	for(int i=1;i<=m;i++) {
		stringTokenizer=new StringTokenizer(br.readLine());
		ti[i]=Integer.parseInt(stringTokenizer.nextToken());
		vi[i]=Integer.parseInt(stringTokenizer.nextToken());
	}
	int []dp=new int[t+5];
	for(int i=1;i<=m;i++) {
		for(int j=t;j>=ti[i];j--) {
				dp[j]=Math.max(dp[j],dp[j-ti[i]]+vi[i]);
			
		}
	}
	System.out.println(dp[t]);
}
}

P1616 疯狂的采药

题目背景

此题为纪念 LiYuxiang 而生。

题目描述

LiYuxiang 是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:"孩子,这个山洞里有一些不同种类的草药,采每一种都需要一些时间,每一种也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。"

如果你是 LiYuxiang,你能完成这个任务吗?

此题和原题的不同点:

1 1 1. 每种草药可以无限制地疯狂采摘。

2 2 2. 药的种类眼花缭乱,采药时间好长好长啊!师傅等得菊花都谢了!

输入格式

输入第一行有两个整数,分别代表总共能够用来采药的时间 t t t 和代表山洞里的草药的数目 m m m。

第 2 2 2 到第 ( m + 1 ) (m + 1) (m+1) 行,每行两个整数,第 ( i + 1 ) (i + 1) (i+1) 行的整数 a i , b i a_i, b_i ai,bi 分别表示采摘第 i i i 种草药的时间和该草药的价值。

输出格式

输出一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

输入输出样例 #1

输入 #1

复制代码
70 3
71 100
69 1
1 2

输出 #1

复制代码
140

说明/提示

数据规模与约定
  • 对于 30 % 30\% 30% 的数据,保证 m ≤ 10 3 m \le 10^3 m≤103。
  • 对于 100 % 100\% 100% 的数据,保证 1 ≤ m ≤ 10 4 1 \leq m \le 10^4 1≤m≤104, 1 ≤ t ≤ 10 7 1 \leq t \leq 10^7 1≤t≤107,且 1 ≤ m × t ≤ 10 7 1 \leq m \times t \leq 10^7 1≤m×t≤107, 1 ≤ a i , b i ≤ 10 4 1 \leq a_i, b_i \leq 10^4 1≤ai,bi≤104。

代码

java 复制代码
import java.util.*;
import java.util.zip.CheckedInputStream;
import java.io.*;
public class Main {
	static int t,m;
	static int []ti;
	static int []vi;
public static void main(String[] args) throws IOException{
	// TODO 自动生成的方法存根
	BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer stringTokenizer=new StringTokenizer(br.readLine());
	 t=Integer.parseInt(stringTokenizer.nextToken());
	 m=Integer.parseInt(stringTokenizer.nextToken());
	ti=new int[m+5];
	vi=new int[m+5];
	for(int i=1;i<=m;i++) {
		stringTokenizer=new StringTokenizer(br.readLine());
		ti[i]=Integer.parseInt(stringTokenizer.nextToken());
		vi[i]=Integer.parseInt(stringTokenizer.nextToken());
	}
	long []dp=new long[t+5];
	for(int i=1;i<=m;i++) {
		for(int j=ti[i];j<=t;j++) {
			
				dp[j]=Math.max(dp[j],dp[j-ti[i]]+vi[i]);
			
		}
	}
	System.out.println(dp[t]);
}
}
相关推荐
莫逸风2 小时前
【java-core-collections】集合框架深度解析
java·开发语言
小江的记录本2 小时前
【分布式】分布式系统核心知识体系:CAP定理、BASE理论与核心挑战
java·前端·网络·分布式·后端·python·安全
bike兔兔2 小时前
Python实现图片批量重命名+统一改名,简单好用图片整理工具
windows
ch.ju2 小时前
Java程序设计(第3版)第二章——switch case break
java
曹牧2 小时前
Spring MVC中使用HttpServletRequest和HttpServletResponse
java·spring·mvc
我命由我123452 小时前
Android 开发,getSystemService 警告信息:Must be one of: Context. POWER_SERVICE ...
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
1candobetter2 小时前
JAVA后端开发—— Maven 生命周期与 IDEA 中Maven 插件面板介绍
java·maven·intellij-idea
Fate_I_C2 小时前
Kotlin 与 Java 互操作空安全处理策略
java·安全·kotlin
zopple2 小时前
Laravel3.x经典特性回顾
android·java·数据库