|
|
package class_2022_09_3_week;
|
|
|
|
|
|
// 来自美团
|
|
|
// 某天,小美在玩一款游戏,游戏开始时,有n台机器,
|
|
|
// 每台机器都有一个能量水平,分别为a1、a2、…、an,
|
|
|
// 小美每次操作可以选其中的一台机器,假设选的是第i台,
|
|
|
// 那小美可以将其变成 ai+10^k(k为正整数且0<=k<=9),
|
|
|
// 由于能量过高会有安全隐患,所以机器会在小美每次操作后会自动释放过高的能量
|
|
|
// 即变成 (ai+10^k)%m
|
|
|
// 其中%m表示对m取模,由于小美还有工作没有完成,所以她想请你帮她计算一下,
|
|
|
// 对于每台机器,将其调节至能量水平为0至少需要多少次操作
|
|
|
//(机器自动释放能量不计入小美的操作次数)。
|
|
|
// 第一行两个正整数n和m,表示数字个数和取模数值。
|
|
|
// 第二行为n个正整数a1, a2,...... an,其中ai表示第i台机器初始的能量水平。
|
|
|
// 1 <= n <= 30000,2 <= m <= 30000, 0 <= ai <= 10^12。
|
|
|
public class Code03_AllNumbersModToZeroMinTimes {
|
|
|
|
|
|
public static int[] times(int n, int m, int[] arr) {
|
|
|
// map[i] : i这个余数变成余数0,需要至少操作几次?
|
|
|
int[] map = new int[m];
|
|
|
bfs(m, map);
|
|
|
int[] ans = new int[n];
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
int num = arr[i];
|
|
|
int minTimes = Integer.MAX_VALUE;
|
|
|
if (num < m) {
|
|
|
minTimes = map[num];
|
|
|
} else {
|
|
|
for (long add = 1; add <= 1000000000; add *= 10) {
|
|
|
int mod = (int) (((long) num + add) % m);
|
|
|
minTimes = Math.min(minTimes, map[mod] + 1);
|
|
|
}
|
|
|
}
|
|
|
ans[i] = minTimes;
|
|
|
}
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
public static void bfs(int m, int[] map) {
|
|
|
boolean[] visited = new boolean[m];
|
|
|
visited[0] = true;
|
|
|
int[] queue = new int[m];
|
|
|
int l = 0;
|
|
|
int r = 1;
|
|
|
// map[0] == 0
|
|
|
// 表示余数0变成余数0,需要至少0次
|
|
|
// 0进队列了, queue[0] = 0
|
|
|
// 0算访问过了,visited[0] = true
|
|
|
while (l < r) {
|
|
|
// 当前弹出的余数是cur
|
|
|
int cur = queue[l++];
|
|
|
// 能加的数字,从1枚举到10^9
|
|
|
for (long add = 1; add <= 1000000000; add *= 10) {
|
|
|
// 比如,m == 7
|
|
|
// 当前余数是cur,cur变成余数0,至少要a次
|
|
|
// 我们想知道 : (哪个余数b + add) % m == cur
|
|
|
// 比如,add=10的时候,cur==5的时候
|
|
|
// 我们想知道 : (哪个余数b + 10) % 7 == 5
|
|
|
// 因为10 % 7 = 3
|
|
|
// 所以其实我们在求 : 哪个余数b + 3 == 5
|
|
|
// 显然b = 5 - 3 = cur - (add % m) = 2
|
|
|
// 再比如,add=10的时候,cur==2的时候
|
|
|
// 我们想知道 : (哪个余数b + 10) % 7 == 2
|
|
|
// 因为10 % 7 = 3
|
|
|
// 所以其实我们在求 : 哪个余数b + 3 == 2
|
|
|
// 这明显是不对的,
|
|
|
// 所以其实我们在求 : 哪个余数b + 3 == 2 + m == 9
|
|
|
// 也就是b,通过加了add % m,来到了m + cur,多转了一圈
|
|
|
// b = 9 - 3 = cur - (add % m) + m = 6
|
|
|
// 也就是说,b = cur - (add % m),
|
|
|
// 如果不小于0,那就是这个b,是我们要找的余数
|
|
|
// 如果小于0,那就是b+m,是我们要找的余数
|
|
|
int from = cur - (int)(add % m);
|
|
|
if (from < 0) {
|
|
|
from += m;
|
|
|
}
|
|
|
// 这个余数我们终于找到了,因为cur变成余数0,需要a次
|
|
|
// 所以这个余数变成余数0,需要a+1次
|
|
|
// 当然前提是这个余数,之前宽度优先遍历的时候,没遇到过
|
|
|
if (!visited[from]) {
|
|
|
visited[from] = true;
|
|
|
map[from] = map[cur] + 1;
|
|
|
queue[r++] = from;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
int m = 100;
|
|
|
int[] map = new int[m];
|
|
|
bfs(m, map);
|
|
|
for (int i = 0; i < m; i++) {
|
|
|
System.out.println(i + " , " + map[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|