Acwing 4083. 最大公约数 方法一:枚举所有数,统计其倍数在输入中的次数
方法二:统计输入数的质因子个数,选最大的一个
O(NlogN)
O(Nsqrt(N))
131. 绝对值表达式的最大值 绝对值转换 + 枚举
AcWing 1295. X的因子链 筛法求素数 + 多重集合全排列
AcWing 4486. 数字操作 分解质因数 + 对数
6115. 统计理想数组的数目 数论+ 组合数学
1735. 生成乘积数组的方案数 类似于6115的题目

一道综合题

AcWing 202. 最幸运的数字
8 是中国的幸运数字,如果一个数字的每一位都由 8 构成则该数字被称作是幸运数字。
现在给定一个正整数 L,请问至少多少个 8 连在一起组成的正整数(即最小幸运数字)是 L 的倍数。
输入格式
输入包含多组测试用例。
每组测试用例占一行,包含一个整数 LL。
当输入用例 L=0 时,表示输入终止,该用例无需处理。
输出格式
每组测试用例输出结果占一行。
结果为 Case i:+一个整数 N,N 代表满足条件的最小幸运数字的位数。
如果满足条件的幸运数字不存在,则 N=0。
数据范围
1≤L≤2×109
输入样例:
8 11 16 0
输出样例:
Case 1: 1
Case 2: 2
Case 3: 0

思路:
第一步:如何表示连续x位8所代表的数字
8...88 = 8 * 1....11 = 8 * 9....99 / 9 = 8 * (10x - 1) / 9
第二步:列式化简
L | 8 * (10x - 1) / 9 -> 9L | 8 * (10x - 1)
d1 = gcd(9L, 8) = gcd(L, 8)则有9L / d1 | 8 / d1 * (10x - 1),又因为gcd(9L / d1, 8) = 1,故9L / d1 | (10x - 1) -> 10x = 1 (mod 9L / d1)
第三步:求解x
c = 9L / d1,有解的充要条件是gcd(c, 10) = 1
第四步:若有解,解是什么
解是10关于c的最小次数,并且有x | euler(c)
故可用试除法求出euler(c),然后用试除法遍历c的所有约数,用快速幂 + 龟速乘找到最小的满足条件的x :::danger 本题会爆LL,离谱 :::

  1. static int l;
  2. static void solve() {
  3. int T = 1;
  4. while (true) {
  5. l = ni();
  6. if (l == 0) break;
  7. long d = gcd(l, 8);
  8. long c = 9L * l / d;
  9. long d2 = gcd(10, c);
  10. if (d2 != 1) {
  11. out.println(String.format("Case %d: %d", T++, 0));
  12. } else {
  13. long euler = getEuler(c);
  14. long res = euler;
  15. for (int i = 1; i <= euler / i; i++) {
  16. if (euler % i == 0) {
  17. long v = qmi(10, i, c);
  18. if (v == 1)
  19. res = Math.min(res, i);
  20. if (euler / i != i) {
  21. v = qmi(10, euler / i, c);
  22. if (v == 1)
  23. res = Math.min(res, euler / i);
  24. }
  25. }
  26. }
  27. out.println(String.format("Case %d: %d", T++, res));
  28. }
  29. }
  30. }
  31. static long qmi(long a, long b, long c) {
  32. long res = 1;
  33. a %= c;
  34. while (b > 0) {
  35. if ((b & 1) == 1)
  36. res = qmul(res, a, c);
  37. b >>= 1;
  38. a = qmul(a, a, c);
  39. }
  40. return res;
  41. }
  42. static long qmul(long a, long b, long c) {
  43. long res = 0;
  44. while (b > 0) {
  45. if ((b & 1) == 1)
  46. res = (res + a) % c;
  47. b >>= 1;
  48. a = (a + a) % c;
  49. }
  50. return res;
  51. }
  52. static long getEuler(long c) {
  53. long res = c;
  54. for (int i = 2; i <= c / i; i++) {
  55. if (c % i == 0) {
  56. while (c % i == 0) {
  57. c /= i;
  58. }
  59. res = res / i * (i - 1);
  60. }
  61. }
  62. if (c > 1) res = res / c * (c - 1);
  63. return res;
  64. }
  65. static long gcd(long x, long y) {
  66. return y == 0 ? x : gcd(y, x % y);
  67. }