Liệt kê các số tự nhiên có số nguyên tố lên đến N theo thứ tự tăng dần


8

Đối với một ndanh sách thừa số nguyên tố nhất định của tất cả các số tự nhiên giữa 1ntheo thứ tự tăng dần. Ví dụ: for n= 10, đầu ra sẽ là:

1:
2: 2^1
3: 3^1
4: 2^2
5: 5^1
6: 2^1 3^1
7: 7^1
8: 2^3
9: 3^2
10: 2^1 5^1

Yêu cầu:

  • Bạn không thể chỉ lặp đi lặp lại các con số và yếu tố từng số. (Trừ khi bạn biết cách tính một số trong thời gian logarit, và sau đó tôi nghi ngờ bạn sẽ lãng phí thời gian để giải các câu đố.) Điều này quá kém hiệu quả.
  • Đầu ra phải như trong ví dụ trên: Trên mỗi dòng số và danh sách các thừa số nguyên tố của nó.
  • Xem xét rằng ncó thể rất lớn, vì vậy có thể không thể tạo ra tất cả các yếu tố vào bộ nhớ và sau đó sắp xếp chúng ở cuối. (Nhưng nếu bạn có một giải pháp thông minh vi phạm điều này, hãy đăng nó.)

Câu trả lời:


4

C ++

Thực hiện một sàng sử dụng các số nguyên tố lên đến sqrt(n). Duy trì một danh sách các danh sách được liên kết để theo dõi các số nguyên tố nào chia số nào sắp tới. Mỗi khi một số nguyên tố pđược sử dụng, Factorcấu trúc của nó được di chuyển pcác vị trí xuống danh sách.

Hầu hết thời gian được dành chỉ để printfing câu trả lời.

#include <stdio.h>
#include <stdlib.h>

// lists of Factors represent known prime factors of a number                                                                                              
struct Factor {
  Factor(int p) : prime(p), next(NULL) { }
  int prime;
  Factor *next;
};

int main(int argc, char *argv[]) {
  long long n = atoll(argv[1]);

  // figure out the maximum prime we need to sieve with                                                                                                    
  int maxp = 1;
  while ((long long)maxp * maxp < n) maxp++;
  maxp--;

  // find next power of two up from that for our circular buffer size                                                                                      
  int size = 1;
  while (size < maxp) size *= 2;
  int mask = size - 1;

  // allocate circular buffer of lists of sieving prime factors for upcoming numbers                                                                       
  Factor **factors = new Factor*[size]();

  printf("1:\n");

  for (long long x = 2; x < n; x++) {
    Factor *list = factors[x & mask];
    factors[x & mask] = NULL; // reset so it can hold the list for x + size                                                                                

    if (!list && x <= maxp) { // x is a prime we need to sieve with - make new list with just itself                                                       
      list = new Factor(x);
    }

    // print factor list, push each Factor along to the next list.                                                                                         
    printf("%lld:", x);
    long long y = x;
    while (list) {
      Factor *f = list;
      list = f->next;
      int p = f->prime;

      // count how many factors of p are in x                                                                                                              
      int k = 1;
      y /= p;
      while (y % p == 0) {
        k++;
        y /= p;
      }
      printf(" %d^%d", p, k);

      // splice f into the list for the next number it divides                                                                                             
      long long z = x + f->prime;
      f->next = factors[z & mask];
      factors[z & mask] = f;
    }
    // remaining part of x must be prime                                                                                                                   
    if (y != 1) printf(" %lld^1", y);
    printf("\n");
  }
}

4

Dưới đây là nỗ lực của tôi, trong sơ đồ R5RS (từ chối trách nhiệm: Tôi thực sự không phải là một Schemer (chưa!), Vì vậy, xin lỗi (có lẽ) mã khủng khiếp).

(define count 10)

; `factors` is our vector of linked-lists of factors.  We're adding to these
; as we go on.
(define factors (make-vector count 'not-found))
(vector-set! factors 0 '())

; `primes-so-far` contains all the prime numbers we've discovered thus far.
; We use this list to speed up the dividing of numbers.
;   `primes-so-far-last` is a ref to the last entry in the `primes-so-far`
; list, for O(1) appending to the list.
(define primes-so-far '(dummy))
(define primes-so-far-last primes-so-far)

;; Helpers
(define (factor-ref n)
  (vector-ref factors (- n 1)))

(define (factor-cached? n)
  (not (eq? (vector-ref factors (- n 1)) 'not-found)))

(define (factor-put n factor)
  (let* ((rest        (/ n factor))
         (factor-cell (cons factor (factor-ref rest))))
    (vector-set! factors (- n 1) factor-cell)
    factor-cell))

(define (prime-append n)
  (let ((new-prime-cell (cons n '())))
    (set-cdr! primes-so-far-last new-prime-cell)
    (set!     primes-so-far-last new-prime-cell)
    new-prime-cell))

;; The factor procedure (assumes that `[1..n-1]` have already been factorized).
(define (factor n)
  (define (divides? m n)
    (= (modulo n m) 0))

  ; n       the number to factor.
  ; primes  the list of primes to try to divide with.
  (define (iter n primes)
    (cond ((factor-cached? n)
           (factor-ref n))

          ((null? primes)
           ; no primes left to divide with; n is prime.
           (prime-append n)
           (factor-put n n)) ; the only prime factor in a prime is itself

          ((divides? (car primes) n)
           (factor-put n (car primes))
           (factor-ref n))

          (else
           (iter n (cdr primes)))))

  (iter n (cdr primes-so-far)))

(define (print-loop i)
  (if (<= i count)
      (begin
        (display i)
        (display ": ")
        (display (factor i))
        (newline)
        (print-loop (+ i 1)))))

(print-loop 1)

In dưới dạng:

1: ()
2: (2)
3: (3)
4: (2 2)
5: (5)
6: (2 3)
7: (7)
8: (2 2 2)
9: (3 3)
10: (2 5)

(Không chính xác như trong mô tả tác vụ, nhưng tất cả những gì bạn phải làm để có được đầu ra đó là gấp danh sách và hợp nhất các lần lặp lại của cùng một số, trong phần đầu ra của mã. Thuật toán / biểu diễn bên trong vẫn sẽ là giống nhau.)

Ý tưởng là lưu trữ các giá trị được tính toán trước đó, nhưng sử dụng thực tế là các yếu tố nlà yếu tố chính đầu tiên nvà các yếu tố chính của (n / yếu tố đầu tiên). Nhưng cái sau đã được biết đến, vì vậy chúng tôi chỉ sử dụng lại danh sách các yếu tố đã có cho số lượng nhỏ hơn đó. Do đó, đối với mỗi số [1..n]không phải là số nguyên tố, một ô khuyết duy nhất được lưu trữ.

Đối với mỗi số, một ô khuyết được tạo và lưu trữ. Vì vậy, phương pháp này nên chạy với O(n)việc sử dụng lưu trữ. Tôi không biết liệu có thể diễn đạt gọn gàng sự phức tạp của thời gian không.


0

C (gcc)

#include <stdio.h>
#include <stdlib.h>

#define true 1
#define false 0

int square(int a){
	return a * a;
}

void prime_factors(int n){
	// this is an array of n elements, which will contain all found primes.
	// curprime stores the index of the last found prime, which saves us searching for where to insert the next one and things.
	int* primes = calloc(sizeof(int), n);
	int curprime = 0;

	printf("1:\n"); // Micro optimization, and rids me of the messing around that is 1.
	for(int i=2; i<=n; i++){
		// Print the current i.
		printf("%i: ",i);

		// Define val, which we'll slowly make smaller and smaller. Mwahaha.
		int val = i;
		int isprime = true;	// This will be set to false if it's divisible by any primes, which of course, means it's also not a prime.

		// Loop through primes, this loop stops if we've reached either more than sqrt(count) primes, or val is equal to zero (as such, it's fully prime factorized).
		for(int*prime_pointer = primes; val && square((int)(prime_pointer-primes)) < curprime; prime_pointer++){
			int prime = *prime_pointer;
			// if the current val is divisible by the current prime.
			while(val%prime == 0){
				isprime = false; 	// We know that this number isn't prime.
				val = val / prime;	// Divide val by it.
				printf("%i ",prime);// And write this prime.
			}
		}
		if(isprime){	// If this number is a prime.
			printf("%i ",i);	// Append it to its own list.
			primes[curprime++] = i;	// And append this new prime to our list of primes.
		}
		printf("\n");	// Terminate the line with a newline. Duh...
	}
}

int main(int argc, char** argv){
	prime_factors(1000);
}

Xác định hàm prime_factorslấy số nguyên nvà đầu ra qua printf theo định dạng sau:

1:
2: 2 
3: 3 
4: 2 2 
5: 5 
6: 2 3 
7: 7 
8: 2 2 2 
9: 3 3 
10: 2 

Điều này sử dụng bộ nhớ thêm O (n) và tôi không chắc độ phức tạp của thời gian.

Hãy thử trực tuyến!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.