【问题标题】:Reducing time complexity to O(1)将时间复杂度降低到 O(1)
【发布时间】:2021-08-15 20:45:24
【问题描述】:

我编写了一个程序,它打印 1 到 d 之间的数字的数量,这些数字可以除以 4 个不同的整数:k、l、m、n。这具有 O(d) 的时间复杂度。但是我读到你可以用 O(1) 的时间复杂度做同样的事情,我不知道怎么做。

int k = in.nextInt();
int l = in.nextInt();
int m = in.nextInt();
int n = in.nextInt();
int d = in.nextInt();

int sum = 0;
int i = 1;
while (i <= d) {
    if (i % k == 0 || i % l == 0 || i % m == 0 || i % n == 0) {
        sum++;
    }
    i++;
}
System.out.println(sum);

【问题讨论】:

  • 你在哪里读到的?
  • 这里是第一段codeforces.com/blog/entry/3819@EJoshuaS
  • 你熟悉inclusion-exclusion principle吗?首先考虑相同问题的更简单情况。例如,0 到 1000 之间有多少个整数可以被 2 或 3 整除?
  • @Brian 是的,我很熟悉这个原理,因为我也在大学学习数学,但我不明白这会如何降低时间复杂度。

标签: java algorithm math time-complexity


【解决方案1】:

假设对于每个数字i,您有一个集合S_i 显示[1, d] 中的数字,它们是i 的乘数。现在我们要计算S_l, S_k, S_m, S_n 的联合大小。等于

|S_l U S_m U S_n U S_k| = |S_l| + |S_m| + |S_n| + |S_k| - |S_l ∩ S_m| - |S_l ∩ S_n| - |S_l ∩ S_k|- |S_m ∩ S_n| - |S_m ∩ S_k| - |S_n ∩ S_k| + |S_l ∩ S_m ∩ S_n| + |S_l ∩ S_m ∩ S_k| + |S_l ∩ S_n ∩ S_k| + |S_m ∩ S_n ∩ S_k| - |S_l ∩ S_m ∩ S_n ∩ S_k|。

您需要的唯一一点是这里两个或多个集合的交集大小等于d/lcm,lcm 是集合的相应数字的最小公倍数。 例如,|S_l ∩ S_m ∩ S_n ∩ S_k| 的大小等于d/lcm(l,m,n,k)。因为,如果一个数可以被多个数整除,那么它一定可以被它们的 lcm 整除。因此,d中的lcm的乘数可以被d/{lcm of the corresponding numbers}统计。

现在,如果您可以假设计算lcm 可以在O(1) 中完成,那么您可以找到|S_l U S_m U S_n U S_k| 的大小。在O(1) 中也是如此。

【讨论】:

    【解决方案2】:

    O(1) 解:

    int main() {
      int arr[4], d;
      for(int i = 0; i < 4; ++i) 
          cin >> arr[i];
      
      int d;
      cin >> d;
    
      int sz = 1 << 4;
    
      int odd, even;
    
      odd = even = 0;
    
      for(int i = 1, i < sz, ++i) {
        int p = 1;
        for(int j = 0; j < 4; ++j) {
          if(i & (1<<j)) p = lcm(p,arr[j]);
        }
        if(__builtin_popcount(i) & 1)
          odd += d / p;
        else even += d / p;
      }
      
      cout << odd - even;
    
      return 0;
    }
    

    【讨论】:

    • #define lcm(a,b) ((a*b)/gcd(a,b))
    猜你喜欢
    • 2022-10-08
    • 2011-06-15
    • 2021-03-29
    • 2012-07-28
    • 2016-10-07
    • 2011-09-03
    • 1970-01-01
    • 2020-09-15
    相关资源
    最近更新 更多