【问题标题】:Number of distinct prime factors of a number一个数的不同质因数的数量
【发布时间】:2013-07-06 22:07:17
【问题描述】:

Q:给定 A、B 和 K。找出 A 和 B(含)之间所有具有 K 个 DISTINCT 质因数的数。 这就是我所做的。我已经实现了埃拉托色尼筛并计算了所有素数,直到 A,B 的上限。然后我继续找出这些素数中的哪一个是 A 和 B 之间数字的因数。如果不同素数的数量等于 K,我增加计数。 我遇到的问题是时间问题。即使在实施筛子之后,计算 2,10000,1 的答案也需要 10 秒(2 到 100000 之间的数字具有 1 个不同的素因子) 这是我的代码

    import math

    #Sieve of erastothenes
    def sieve(n):
        numbers=range(0,n+1)
        for i in range(2,int(math.ceil(n**0.5))):
            if(numbers[i]):
                for j in range(i*i,n+1,i):
                    numbers[j]=0

        #removing 0 and 1 and returning a list          
        numbers.remove(1)
        prime_numbers=set(numbers)
        prime_numbers.remove(0)

        primes=list(prime_numbers)
        primes.sort()
        return primes

    prime_numbers=[]
    prime_numbers=sieve(100000)
    #print prime_numbers
    def no_of_distinct_prime_factors(n):

        count=0
        flag=0
        #print prime_numbers
        for i in prime_numbers:
            #print i
            if i>n:
                break
            if n%i==0:
                count+=1
                n=n/i
        return count
    t=raw_input()
    t=int(t)
    foo=[]
    split=[]
    for i in range (0,t):
        raw=raw_input()
        foo=raw.split(" ")
        split.append(foo)
    for i in range(0,t):
        count=0
        for k in range(int(split[i][0]),int(split[i][1])+1):
            if no_of_distinct_prime_factors(k)==int(split[i][2]):
                count+=1
        print count

关于如何进一步优化它的任何提示?

【问题讨论】:

    标签: python primes sieve-of-eratosthenes prime-factoring


    【解决方案1】:

    这应该做你想做的事情:

    max=100000
    k=6
    nb_factors=[1]*max
    for i in range(2,max):
        if nb_factors[i] == 1:
            for j in range(i, max, i):
                nb_factors[j]+=1
    
    print [(i,f) for i,f in enumerate(nb_factors) if f > k]
    

    我还没有检查正确性(尤其是对于像 0 和 1 这样的边缘情况),但它似乎没问题(您可以在第 3 行和第 5 行将 1 替换为 0,具体取决于您是否要在列表中包含 1因素)。

    【讨论】:

      【解决方案2】:

      我不知道python [ ;( ],但我知道如何优化它。 我们可以在这里使用线性筛 - 它是对 Erastothenes 筛的改进,适用于 O(n) 并允许快速分解(O(k),其中 k 是分解中素数的数量)。

      我们要做的是有 2 个数组 - pr(具有素数的数组:pr[i] 是第 i 个素数)和 lp(具有最少除数的数组:lp[i] 是i) 的除数的最小数。 lp 数组中的初始值为零。 我们将遍历 [2, X] 中的所有数字。对于每个数字(我们称之为 i),有 2 种可能的变体: 1. lp[i] = 0 表示i之前没有数是i的除数,所以i是素数。 2. lp[i] != 0 意味着 i 不是素数(我们已经找到了它的最小除数)。 现在让我们考虑所有的数字 x[j] = i * pr[j]。如果 pr[j] 满足 pr[j]

      那么我们可以编写如下代码(C++,因为我对python不熟悉):

      const int N = 100001; //the maximum possible input
      int lp[N+1];
      vector<int> pr;
      
      void init()
      {
          for (int i=2; i<=N; ++i) 
          {
              if (lp[i] == 0) //i is prime
              {
                  lp[i] = i;
                  pr.push_back (i);
              }
              for (int j=0; j<pr.size() && pr[j]<=lp[i] && i*pr[j]<=N; ++j)
                  lp[i * pr[j]] = pr[j];
          }
      }
      

      现在我们有了 lp 数组,我们可以轻松地分解每个数字 n:lp[n] 是 n 的除数。然后我们可以分配 n = n / lp[n] 并继续这个过程。 由于 lp 是最小除数,因式分解中的所有除数只能以升序出现。所以计算不同素数的数量非常容易:

      int count(int n)
      {
          int ans = 0;
          int curprime = 0;
          while (n!=1)
          {
              int minp = lp[n];
              if (minp != curprime) ++ans, curprime = minp;
      
              n/=minp;
          }
          return ans;
      }
      

      然后我们可以只看 [A,B] 中的每个数字并计算 dist 的数量。回答问题的主要除数:

      int f(int a, int b, int c)
      {
          int cnt = 0;
          for (int i = a; i <= b; ++i)
              if (count(i)==c)
                  ++cnt;
          return cnt;
      }
      

      即使是测试 (2,1000000,1) 也运行不到 1 秒:http://ideone.com/rMTIBj

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-17
      • 2017-02-25
      • 2021-03-30
      • 2020-09-04
      • 2019-04-26
      • 2019-10-21
      相关资源
      最近更新 更多