You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
1.9 KiB

2 years ago
package class_2022_04_3_week;
// 来自微众
// 4.11笔试
// 给定n位长的数字字符串和正数k求该子符串能被k整除的子串个数
// (n<=1000k<=100)
public class Code05_ModKSubstringNumbers {
// 暴力方法
// 为了验证
public static int modWays1(String s, int k) {
int n = s.length();
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
if (Long.valueOf(s.substring(i, j + 1)) % k == 0) {
ans++;
}
}
}
return ans;
}
// 正式方法
// 时间复杂度O(N * k)
public static int modWays2(String s, int k) {
int[] cur = new int[k];
// 帮忙迁移
int[] next = new int[k];
// 0...i 整体余几?
int mod = 0;
// 答案:统计有多少子串的值%k == 0
int ans = 0;
for (char cha : s.toCharArray()) {
for (int i = 0; i < k; i++) {
// i -> 10个
// (i * 10) % k
next[(i * 10) % k] += cur[i];
cur[i] = 0;
}
int[] tmp = cur;
cur = next;
next = tmp;
mod = (mod * 10 + (cha - '0')) % k;
ans += (mod == 0 ? 1 : 0) + cur[mod];
cur[mod]++;
}
return ans;
}
// 为了测试
public static String randomNumber(int n) {
char[] ans = new char[n];
for (int i = 0; i < n; i++) {
ans[i] = (char) ((int) (Math.random() * 10) + '0');
}
return String.valueOf(ans);
}
// 为了测试
public static void main(String[] args) {
int N = 18;
int K = 20;
int testTime = 10000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
String str = randomNumber((int) (Math.random() * N) + 1);
int k = (int) (Math.random() * K) + 1;
int ans1 = modWays1(str, k);
int ans2 = modWays2(str, k);
if (ans1 != ans2) {
System.out.println("出错了!");
System.out.println(str);
System.out.println(k);
System.out.println(ans1);
System.out.println(ans2);
break;
}
}
System.out.println("测试结束");
}
}