当前位置:   article > 正文

Codeforces Round 911 (Div. 2) --- D题题解_codeforces round 912 (div. 2)insert and equalize

codeforces round 912 (div. 2)insert and equalize

D. Small GCD

 

Problem - D - Codeforces

题目大意:

给你一个数组,你可以在里面任选三个数ai aj ak,要求i j k 互不相同, 现定义一个函数f(a,b,c)=gcd(a,b),其中a 和 b为a,b,c中较小的两个。求f(a,b,c)的累加和。更通常的说就是求

思路解析:

因为他是求任意三个数的函数值的累加和,所以我们ai aj ak的位置并不影响答案,那我们可以直接将整个数组排序,因为对于 ai aj定了之后 ak可以是任意的(ak > ai, ak > aj),即k能选取的范围就是gcd(ai, aj)的次数。如果排序后 确定ai aj 后我们直接使gcd(ai, aj) * (n-j).

但是我们暴力枚举 ai 和 aj 的话,时间复杂度大概为 O(5*10^9),这个会被卡住,所以我们需要想到一个好的方法,又因为100000它的因子最多为128个,我们可以直接预处理,得到【1,100000】的每个数的所有因子,这样我们就把它的公因数控制住了,当公因数为t时,能贡献多少答案,但是公因数为t,它的最大公因数可能为t的倍数,所以这里需要使用容斥原理来做。

答案怎么统计?

  1. for (int i = 0; i < n; i++) {
  2. for (int j = 0; j < 128; j++) {
  3. if (num[arr[i]][j] == 0) break;
  4. // (n - i - 1) k 可以枚举多少个
  5. // num[arr[i]][j] 公因数
  6. // nums[num[arr[i]][j]] 公因数的个数
  7. f[num[arr[i]][j]] += (long) nums[num[arr[i]][j]] * (n - i - 1);
  8. nums[num[arr[i]][j]]++;
  9. }
  10. }

之前的个数因数为t的数有nums[num[arr[i]][j]]个,所以对于当前这个b来说他的a有nums[num[arr[i]][j]]个选择,然后乘以c能选择的个数。

代码:

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.StreamTokenizer;
  5. import java.util.Arrays;
  6. /**
  7. * @ProjectName: study3
  8. * @FileName: Ex31
  9. * @author:HWJ
  10. * @Data: 2023/11/27 9:29
  11. */
  12. public class Ex31 {
  13. static int[][] num = new int[100005][128];
  14. public static void main(String[] args) throws IOException {
  15. for (int i = 1; i <= 100000; i++) {
  16. int k = 0;
  17. for (int j = 1; j <= Math.sqrt(i); j++) {
  18. if (i % j == 0) {
  19. num[i][k++] = j;
  20. if (j != i / j) {
  21. num[i][k++] = i / j;
  22. }
  23. }
  24. }
  25. }
  26. StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
  27. in.nextToken();
  28. int t = (int) in.nval;
  29. for (int o = 0; o < t; o++) {
  30. in.nextToken();
  31. int n = (int) in.nval;
  32. int[] arr = new int[n];
  33. int[] nums = new int[100005];
  34. long[] f = new long[100005];
  35. for (int i = 0; i < n; i++) {
  36. in.nextToken();
  37. arr[i] = (int) in.nval;
  38. }
  39. Arrays.sort(arr);
  40. long ans = 0;
  41. for (int i = 0; i < n; i++) {
  42. for (int j = 0; j < 128; j++) {
  43. if (num[arr[i]][j] == 0) break;
  44. // (n - i - 1) k 可以枚举多少个
  45. // num[arr[i]][j] 公因数
  46. // nums[num[arr[i]][j]] 公因数的个数
  47. f[num[arr[i]][j]] += (long) nums[num[arr[i]][j]] * (n - i - 1);
  48. nums[num[arr[i]][j]]++;
  49. }
  50. }
  51. for (int i = 100000; i >= 1; i--) {
  52. for (int j = i + i; j <= 100000; j+=i) {
  53. f[i] -= f[j]; // 容斥处理
  54. }
  55. }
  56. for (int i = 100000; i >= 1; i--){
  57. ans += f[i] * i;
  58. }
  59. System.out.println(ans);
  60. }
  61. }
  62. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/55194
推荐阅读
相关标签
  

闽ICP备14008679号