题目概览
做法1:模拟
import java.util.*;
public class Main {
static int n, k, m;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
n = Integer.parseInt(str[0]);
k = Integer.parseInt(str[1]); k++;
m = Integer.parseInt(str[2]);
LinkedList<Integer> queue = new LinkedList<>();
for (int i = k; i <= n; i++) queue.offer(i);
for (int i = 1; i < k; i++) queue.offer(i);
while (queue.size() > 1) {
for (int i = 1; i < m; i++) {
queue.offer(queue.peek());
queue.pop();
}
queue.pop();
}
System.out.println(queue.pop() - 1);
}
}
数学推导
视频讲解 https://www.bilibili.com/video/BV1UB4y117Hz?t=758.6
逆向递推
考虑简单情况从编号为0的位置开始数数
数到只有最后一个人时,那么最后一个数的位置(pos)就是0
从该位置去推上一层(第二层)的位置,即pos = m % 2;
再根据第二层的位置推第三层的位置,我们发现直接从pos来推
并不好推出来,那么我们可以采用第一层的思想:看看编号为0
的数在上一层的位置是多少:pos0 = m % 3, 那么pos
(m % 2) 在上一层的位置就很显然了:pos = (pos0 + (m % 2)) % 3, 即有着(m % 2)的偏移量
不断递推得出结果:
int pos = 0;
for (int i = 2; i <= n; i++) {//一共会递推n - 1次
pos = (pos + m) % i;
}
完整代码
import java.util.*;
public class Main {
static int n, k, m;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
n = Integer.parseInt(str[0]);
k = Integer.parseInt(str[1]);
m = Integer.parseInt(str[2]);
int pos = 0;
for (int i = 2; i <= n; i++) pos = (pos + m) % i;
//pos最后是从编号为0开始时的最终结果,对于本题加上k即可
System.out.println((pos + k) % n);
}
}
acwing(3630) 报数问题
https://www.acwing.com/file_system/file/content/whole/index/content/4186556/
代码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int pos = 0;
for (int i = 2; i <= n; i++) pos = (pos + 3) % i;
System.out.println(pos + 1);
}
}
改编问题:(acwing)1445题:招聘
https://www.acwing.com/file_system/file/content/whole/index/content/4184390/
不同的是m是动态的,在进行递推时我们是从走往前递推,因
此我们需要,将A数组进行倒着遍历,总而言之本质上是不变
的,值得注意的是k要小于n,注意取模操作即可,或者将A数组进行扩容至与n对应
#### 具体代码如下
import java.util.*;
import java.io.*;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static final int N = 1010;
static int[] A = new int[N];
static int n, m;
public static void main(String[] args) throws IOException {
int T = Integer.parseInt(br.readLine());
while (T -- > 0) {
String[] str = br.readLine().split(" ");
n = Integer.parseInt(str[0]);
m = Integer.parseInt(str[1]);
for (int i = 1; i <= m; i++) A[i] = Integer.parseInt(str[i + 1]);
//由于下标从1开始,导致第m个数会取不到,即j%m==0时当成m即可
A[0] = A[m];
int pos = 0;
//添加j指针(也可以不添加)明确次数
for (int i = 2, j = n - 1; i <= n; i++, j--) pos = (pos + A[j % m]) % i;
System.out.println(pos);
}
}
}