Tìm số nguyên tố mà không sử dụng các ký tự nguyên tố


21

Nhiệm vụ của bạn, nếu bạn chọn chấp nhận nó, là viết một chương trình / hàm chấp nhận một số nguyên N làm đầu vào. Chương trình / hàm sẽ xuất / trả về danh sách các số nguyên tố N đầu tiên . Nhưng đây là điểm thu hút: bạn không được phép sử dụng các ký tự chính trong mã của mình. Một ký tự chính là một ký tự có điểm mã Unicode là số nguyên tố. Trong phạm vi ASCII có thể in, đây là:

%)+/5;=CGIOSYaegkmq

Nhưng quy tắc cũng áp dụng cho các ký tự không phải ASCII nếu mã của bạn sử dụng các ký tự đó.

  • Đầu vào hợp lệ là một số nguyên N trong đó 0 <N <= T , trong đó bạn có thể chọn T , nhưng nó phải lớn hơn hoặc bằng 10000. T không phải là hữu hạn.
  • Đối với các đầu vào không hợp lệ (không phải là số nguyên, số nguyên nằm ngoài phạm vi), hãy ném ngoại lệ hoặc đầu ra / trả về không có gì / null.
  • Một số nguyên có khoảng trắng hàng đầu / dấu làm đầu vào được coi là không hợp lệ.
  • Một số nguyên có +ký tự là dấu đầu vào được coi là không hợp lệ.
  • Một số nguyên có các số 0 đứng đầu làm đầu vào được coi là hợp lệ.
  • Nếu ngôn ngữ của bạn cho phép bạn chuyển một số nguyên đã được phân tích cú pháp làm đầu vào, các quy tắc phân tích cú pháp ở trên (ngoại trừ phạm vi một) không áp dụng, vì int đã được phân tích cú pháp.
  • Đầu vào luôn là cơ sở-10.
  • Không được phép sử dụng các bộ tạo nguyên tố tích hợp và bộ kiểm tra tính nguyên thủy (bao gồm các hàm thừa số nguyên tố).
  • Hạn chế nguồn được áp đặt cho các ký tự Unicode, nhưng việc đếm byte cho điểm có thể ở dạng mã hóa khác nếu bạn muốn.
  • Đầu ra có thể chứa một dòng mới duy nhất, nhưng điều này là không bắt buộc.
  • Nếu bạn xuất / trả về danh sách số nguyên tố dưới dạng một chuỗi, thì mọi số nguyên tố phải được phân cách bằng một hoặc nhiều char không có chữ số. Bạn có thể chọn dấu phân cách bạn sử dụng.
  • Đây là một thử thách , mã ngắn nhất tính bằng byte thắng.

Chồng đoạn để xác minh mã của bạn

Bạn có thể sử dụng Đoạn mã dưới đây để xác minh rằng mã của bạn không chứa các ký tự chính:

var primes=[],max=10000;for(var i=2;i<=max;i++){primes.push(i);}for(var N=2;N<Math.sqrt(max);N++){if(primes.indexOf(N)===-1){continue;}primes=primes.filter(function (x){return x===N||x%N!==0;});}function setText(elem,text){var z=('innerText' in elem)? 'innerText' : 'textContent';elem[z]=text;}function verify(inputCode,resultSpan){var invalidChars=[];var success=true;for(var i=0;i<inputCode.length;i++){var cc = inputCode.charCodeAt(i);if (cc>max){setText(resultSpan,"Uh oh! The char code was bigger than the max. prime number calculated by the snippet.");success = false;break;}if (primes.indexOf(cc)!==-1){invalidChars.push(inputCode[i]);}}if (invalidChars.length===0&&success){setText(resultSpan, "Valid code!");}else if(success) {  var uniqueInvalidChars = invalidChars.filter(function (x, i, self){return self.indexOf(x)===i;});setText(resultSpan, "Invalid code! Invalid chars: " + uniqueInvalidChars.join(""));    }}document.getElementById("verifyBtn").onclick=function(e){e=e||window.event;e.preventDefault();var code=document.getElementById("codeTxt").value;verify(code,document.getElementById("result"));};
Enter your code snippet here:<br /><textarea id="codeTxt" rows="5" cols="70"></textarea><br /><button id="verifyBtn">Verify</button><br /><span id="result"></span>


10
Điều đó thật tàn nhẫn khi ;bị cấm ...
20/2/2015

Nếu người kiểm tra tính nguyên thủy không được phép, vậy còn chức năng nhân tố chính.
Maltysen

@Maltysen Từ các hàm thừa số nguyên tố, bạn có thể nhanh chóng xem liệu một số có phải là số nguyên tố hay không, vì vậy tôi sợ điều đó không được phép. Tôi sẽ làm rõ điều đó.
Chương trìnhFOX

Chúng tôi có bắt buộc phải loại bỏ một số đầu vào không hợp lệ này không? Chẳng hạn, nếu hàm chuỗi-> int của ngôn ngữ của chúng ta cho phép dẫn đầu +, có vẻ đáng thất vọng khi được yêu cầu loại bỏ chúng theo cách thủ công.
Runer112

11
Tôi đã rất phấn khích về điều này và bắt đầu vào một giải pháp, sau đó nhận ra rằng các parens kín không được phép. Vâng, tôi ra ngoài.
Alex A.

Câu trả lời:


10

CJam, 19 18 30 34 33 19 17 21 20 byte

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

{_3\#,2>__ff*:~-<N*}

Đây có lẽ là một trong những thuật toán kém hiệu quả nhất mà tôi từng thực hiện. Nhưng tôi đã làm nó cho kích thước!

Câu trả lời của tôi bao gồm một khối mã, hoạt động như một hàm ẩn danh trong CJam. Chạy nó với một số nguyên ngay trước nó trên ngăn xếp và danh sách kết quả được đổ vào ngăn xếp. Tôi coi giới hạn trên của đầu vào là vô hạn vì vậy tôi không phải kiểm tra ràng buộc đó.

Thuật toán của tôi bắt đầu bằng cách tăng 3 lên công inputsuất thứ, được đảm bảo cung cấp một số lớn hơn số inputnguyên tố thứ nếu đầu vào hợp lệ. Sau đó, một danh sách các số nguyên từ 2 đến số này trừ đi một số được tạo ra, đó là một dải đủ lớn để chứa tất cả các số nguyên tố chúng ta muốn. Để loại bỏ các số tổng hợp ... thở dài ... chúng tôi tạo một danh sách mọi sản phẩm theo cặp, sẽ tạo ra tất cả các số tổng hợp từ 4 đến một giá trị lớn ngu ngốc, đủ lớn cho mục đích của chúng tôi. Sau đó, chỉ là vấn đề loại bỏ mọi yếu tố khỏi danh sách ban đầu trong danh sách tổng hợp này, cắt giảm nó xuống đầu tiêninput yếu tố và nối các yếu tố với ký tự dòng mới.

Các thuật toán nên làm việc cho bất kỳ đầu vào. Tuy nhiên, việc trình thông dịch / máy tính có đủ bộ nhớ hay thời gian hay không là một câu hỏi hoàn toàn khác, bởi vì các yêu cầu về thời gian và không gian là theo cấp số nhân đối với đầu vào. Vì vậy, nếu đầu vào lớn hơn khoảng 5 cho trình thông dịch trực tuyến hoặc khoảng 8 cho người ngoại tuyến, thì câu trả lời cho câu hỏi đó có lẽ là không.


3
heh, ở tuổi 17, bạn có số byte chính trong câu trả lời của mình.
Corey Ogburn 20/2/2015

Tại sao bạn cần một S*?
jimmy23013

@ user23013 Đầu vào không hợp lệ dưới 1 vẫn cung cấp thông qua thuật toán, chúng chỉ tạo ra một danh sách trống. Nhưng đó không phải là đầu ra hợp pháp cho họ, vì vậy tôi tham gia các yếu tố danh sách có khoảng trắng để tạo đầu ra trống cho các đầu vào không hợp lệ này.
Runer112

1
Tôi đã nhận thấy điều này, không phải Slà một nhân vật chính?
Zacharý

Đó là một nhân vật chính. Tôi biết tôi đã trễ hơn 2 năm khi nói điều này, nhưng câu trả lời này không hợp lệ
Zacharý

8

Java. 474 byte

i\u006dport j\u0061v\u0061.util.*\u003bvoid b(int b\u0029{Lon\u0067 c\u003d2L,d,f[]\u003d{}\u003bfor(f\u003dArr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029for(d\u003d0L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029for(lon\u0067 h:f\u0029d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003bj\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029,Lon\u0067.cl\u0061ss\u0029\u003b}

Đưa đầu vào thông qua đối số chức năng, đầu ra thông qua ngoại lệ ném.

Thụt lề:

i\u006dport j\u0061v\u0061.util.*\u003b
void b(int b\u0029{
    Lon\u0067 c\u003d2L,d,f[]\u003d{}\u003b
    for(f\u003dArr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029
        for(d\u003d0L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029
            for(lon\u0067 h:f\u0029
                d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003b
    j\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029,Lon\u0067.cl\u0061ss\u0029\u003b
}

Đã xóa các ký tự:

import java.util.*;
void b(int b){
    Long c=2L,d,f[]={};
    for(f=Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
        for(d=0L;f[b]<1;f[b]=d<1?c:0,d=0L,c++)
            for(long h:f)
                d=h>0&&c/h*h==c?1:d;
    javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class);
}

Giải trình:

Long c,d,f[]={};                                                //Initialize variables.

for(f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
    f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L)            //Initialize f to an array of 0's.
                                                     b-->0      //Iterate over the first b primes.

for(d=0L;f[b]<1;f[b]=d<1?c:0,d=0L,c++)
    d=0L                        d=0L                            //Initialize d to 0.
         f[b]<1                      c++                        //Increment c while the b'th prime is 0.
                f[b]=d<1?c:0                                    //If d = 0, the b'th prime = c, else continue.

for(long h:f)                                                   //Iterate over all found primes.

d=h>0&&c/h*h==c?1:d;
  h>0                                                           //Ignore non-found primes.
       c/h*h==c                                                 //Equivalent to c%h==0
               ?1:d                                             //If h is prime and c is divisible by h, d = 1. Otherwise d stays unchanged.

javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class)   //Print solution to stderr
javax.xml.bind.JAXB.unmarshal(                   ,Long.class)   //Prints what's contained to stderr.
                                 Arrays.asList(f)               //Convert f to list.
                              ""+                               //Convert to string.

Giải pháp ban đầu của tôi đã sử dụng một returntuyên bố. Sau khi hỏi câu hỏi này trên StackOverflow, regettman đã đủ tử tế để cung cấp một cách để xuất / trả lại mà không cần sử dụng các chữ cái chính.

Như thường lệ, các đề xuất đều được chào đón :)


3
+1. Điều đó đã phải thực sự khó khăn cho bạn và rgettman để tìm ra. Rất ấn tượng. :)
TNT

5

Ruby, 74

->n,*o{o<<[2..n*n][0].find{|x|!o.find{|y|1.>x.^y.*x.div y}}until o[n-1]
o}

Giải trình:

*okhởi tạo một mảng đầu ra trống. cho đến khi nó có ncác mục, chúng tôi tìm thấy số nhỏ nhất> = 2 không chia bất kỳ mục nào hiện tại o, sau đó thêm nó vào o. Để kiểm tra phân chia, yike. Tất cả các toán tử tốt đều không được phép và thậm chí tôi không thể sử dụng divmod. Tốt nhất tôi có thể thấy là sử dụng x.div y, lấy x chia cho y và làm tròn xuống, sau đó nhân số đó với y một lần nữa. Nếu nó bằng x, không có làm tròn, vì vậy y chia x. 1.>x.^là kiểm tra tính bằng nhau, kiểm tra xem kết quả của xor có bằng 0. Việc .trước mỗi toán tử là do bạn không thể trộn. các cuộc gọi toán tử dấu ngoặc đơn và các cuộc gọi phương thức không có dấu ngoặc đơn.

Chỉnh sửa: Các thông số kỹ thuật kiểm tra phạm vi đã được thêm vào sau khi tôi đăng bài này, tôi nghĩ vậy. Để tuân thủ yêu cầu 79 ký tự:

->n,*o{o<<[*2..-~n*n].find{|x|!o.find{|y|1.>x.^y.*x.div y}}until o[n-1]||n<1
o}

4

CJam, 38 37 30 byte

{_~2#,2>\{(\{1$37c~},\p}*'<(~}

Hãy thử nó ở đây

Tôi nghĩ rằng điều này phải tuân thủ tất cả các quy tắc và hoạt động cho bất kỳ N không âm (tức là T là vô hạn). Mặc dù nó không hiệu quả khủng khiếp, vì vậy đừng thử với số lượng lớn.

Đây là một khối - thứ gần nhất với hàm (chưa được đặt tên) - dự kiến ​​một số nguyên trên ngăn xếp, in tất cả các số nguyên tố và rời khỏi ngăn xếp mà không cần đầu vào. Đối với tất cả các đầu vào không hợp lệ, nó sẽ gây ra lỗi hoặc không in gì cả.

Hầu hết các mã là xác nhận đầu vào, tiếp theo là sàng của Eratosthenes. Tôi chỉ cần làm việc xung quanh hạn chế đầu vào ở 3 nơi:

  • )là sự gia tăng trong CJam. Tôi cần điều đó một lần, nhưng có thể thay thế nó bằng ~(bổ sung bitwise) bởi vì dù sao tôi cũng đã bình phương các con số.
  • %là modulo. Tôi đang sử dụng 37c~thay thế, lần đầu tiên tạo ra nhân vật% và sau đó là eval. Điều này làm cho mã chậm hơn rất nhiều.
  • ;bật và loại bỏ một yếu tố từ ngăn xếp. Tôi cần phải làm điều này vào cuối. Thay vào đó, tôi đang sử dụng '<(~cái mà đẩy nhân vật <, làm giảm giá trị của nó và đánh bại nó.

Tôi nghĩ rằng, với tất cả các quy tắc phân tích cú pháp đầu vào, chúng tôi không được phép lấy một số nguyên đã được phân tích cú pháp.
Runer112

@ Runer112 Chúng tôi được phép viết "một hàm chấp nhận số nguyên". Không phải "một hàm chấp nhận biểu diễn chuỗi của một số nguyên".
Martin Ender

3

Bash + coreutils, 227 byte

printf -vb br`dc<<<Di14B8209P`
printf -vc -- $[$1-0]
[ "${1#$c}" -o $c -lt 1 ]||{
for i in {2..104729}
{
for f in `jot $[i-1] $[i-1] 1`
{
[ 0 -lt `dc<<<"$i $f~p"` ]||$b
}
[ $f -lt 2 ]&&printf $i\ &&: $[c--]
[ $c -lt 1 ]&&$b
}
}

Điều này khá khó khăn. Một số điều tôi gặp phải:

  • Hầu hết các vòng lặp ( whileuntil) đều không sử dụng được vì chúng gần giống với donetừ khóa shell và không thể là kết quả của việc mở rộng biến (trừ khi evalđược sử dụng, nhưng điều đó cũng bị loại bỏ). Vòng lặp có thể sử dụng duy nhất là for/ incho phép {/ }thay vì do/ done. for (( ; ; ))cũng không thể sử dụng được.
  • = đã hết, vì vậy chúng ta cần một cách khác để gán biến. printf -vlà tốt cho việc này.
  • Chúng ta biết rằng p (10000) là 104729 vì vậy đối với vòng ngoài cho các số nguyên tố tiềm năng, chúng ta có thể chỉ cần lặp từ 2 đến 104729 và ngắt một khi chúng ta có đủ số nguyên tố
  • jottạo danh sách các yếu tố tiềm năng trong vòng lặp bên trong. Nếu một yếu tố tiềm năng phân chia một số nguyên tố tiềm năng, thì đó không phải là số nguyên tố và chúng ta thoát ra sớm
  • May mắn thay breaklà một shellin và không phải là một từ khóa, vì vậy có thể được tạo ra như là kết quả của việc mở rộng. dcchuyển đổi một số cơ sở 13 thành bytestreameak .
  • Để kiểm tra xem một yếu tố tiềm năng có chia một số nguyên tố tiềm năng hay không, chúng ta không thể sử dụng các toán tử số học thông thường /hoặc hệ %vỏ. Vì vậy, điều này được gia công cho toán tử dcs ~, nó đẩy thương số và phần còn lại vào ngăn xếp.
  • -lt - ít hơn - là toán tử so sánh shell duy nhất có thể sử dụng.
  • echokhông sử dụng cho đầu ra. printfhoạt động mặc dù miễn là chúng ta tránh%

Có được xác nhận đầu vào đúng là một chút khó khăn. Điều này trả về không có gì trong trường hợp đầu vào không hợp lệ.

Đầu ra:

$ ./primenoprime.sh 10
2 3 5 7 11 13 17 19 23 29 $ 

3

Haskell, 90 byte

\n->[fst c|c<-zip[p|p<-[2..],not$or[b>p-1&&b-1<p|b<-[u*v|u<-[2..p-1],v<-[2..p-1]]]][1..n]]

Đây là một hàm ẩn danh lấy một số nguyên nlàm đầu vào.

Cách thức hoạt động: [p|p<-[2..],not$or[b>p-1&&b-1<p|b<-[u*v|u<-[2..p-1],v<-[2..p-1]]]](ví dụ đầu tiên về số một số nguyên tố tại wiki Haskell nhưng với elemchức năng được thay thế) tạo ra một danh sách vô hạn các số nguyên tố. zipnó với những con số từ 1đến nđể thực hiện một danh sách các (prime, seq. number)cặp. Hủy bỏ seq. số, một lần nữa. Kết quả là một danh sách các số nguyên tố có độ dài n.


1

Rust, 64897 byte

|n|println!{"{:?}",&[2,3,6-1,7,11,13,17,19,23,29,31,37,41,43,47,60-7,0x3b,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,0x97,0x9d,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,0xfb,0x101 ...}

(mã bị cắt do giới hạn ký tự, giải pháp đầy đủ ở đây )

Các tính năng rỉ sau đây trở nên không khả dụng do hạn chế chính:

  • chức năng gọi, vì họ yêu cầu ')'
  • ràng buộc thường xuyên, vì họ yêu cầu cho phép (e)
  • định nghĩa vĩ mô, họ yêu cầu quy tắc vĩ mô! (a, e, m)
  • câu lệnh khớp, chúng yêu cầu khớp (a, m) và => (=)
  • khả năng biến đổi, vì nó luôn được giới thiệu với từ khóa mut (m).
  • trở lại (e), phá vỡ (a, e), tiếp tục (e)
  • khác (e)

Những gì bạn có thể sử dụng về mặt kỹ thuật:

  • nếu. Nhưng không có gì khác, chúng vô dụng trong bối cảnh biểu hiện, vì vậy chỉ tốt cho tác dụng phụ.
  • macro. Các macro tiêu chuẩn như in! thường được theo sau bởi (), nhưng thực sự sử dụng {} hoặc [] thay vào đó là hợp pháp. Không có điều này, nhiệm vụ sẽ là không thể.
  • đóng cửa, theo nghĩa hẹp nhất. Bạn không thể gọi chúng (yêu cầu ()) hoặc ràng buộc chúng (yêu cầu cho phép), nhưng bạn có thể xác định một cái không đệ quy. Không có điều này, nhiệm vụ rõ ràng sẽ trở thành không thể.
  • cấu trúc.
  • cho các vòng lặp. Đây là những triển vọng, vì chúng thực sự cho phép liên kết biến và chúng có một trình vòng lặp, vẫn có thể được xác định bằng cú pháp phạm vi. Trình lặp thậm chí có thể là một biểu thức.
  • Toán tử dựng sẵn, ngoại trừ +,% và /. Các toán tử logic ngắn mạch có vẻ đầy hứa hẹn.

Tôi chỉ đơn giản là không thể làm bất cứ điều gì Turing - hoàn thành với các công cụ này. Tôi xin lôi. Tất cả những gì còn lại là bao gồm 10000 số nguyên tố đầu tiên, được làm sạch 5 giây. Ít nhất bạn có thể cắt nó và có một giải pháp hợp lệ, theo nghĩa hẹp nhất có thể.

Tôi rất muốn các chuyên gia về lặn Turing tarpit (hoặc trên Rust!) Nói cho tôi biết nếu tôi có thể làm gì tốt hơn!


1

GNU APL, 75 68 67 65 59 56 55 ký tự

⎕IOphải 1.

∇z←p n
z←2,j←3
j←j--2
→2×⍳∨⌿1>z|j
z←z,j
→2×⍳n>⍴z
z←n↑z∇

Tôi đã trở lại vào tháng này sau đó nhận ra rằng tôi có thêm một không gian!


Đây có phải là mã hóa APL hoặc UTF-8 không? Nếu bạn chuyển đổi nó thành mã hóa APL (và nó hợp lệ) thì nó sẽ ngắn hơn nhiều byte.
NoOneIsHere

UTF-8. Vâng, nhưng tại những điểm nhân vật thấp đó, sẽ có nhiều số nguyên tố hơn.
Zacharý

Nói chính xác, giờ đây byte được tính bằng APL, nhưng hạn chế về nguồn là Unicode. (Tôi nhận ra thử thách cho phép đếm byte không Unicode)
Zacharý

0

Pyth - 12 byte

Sử dụng hàm thừa số nguyên tố của pyth để xem # có phải là số nguyên tố không. Công dụng!tPT thủ thuật gợi ý cho tôi theo câu trả lời của tôi cho các số nguyên tố dưới hàng triệu vấn đề.

<f!tPTr2^T6Q

Vì bộ lọc chỉ hoạt động cho các số nguyên tố dưới n chứ không phải n đầu tiên, tôi chỉ tìm kiếm nghịch đảo của pi (x) với 10.000 và nhận 104.000 nên tôi sử dụng các số nguyên tố dưới 10⁶ và nhận được số nguyên tố đầu tiên. Điều này không thực sự chạy, vì vậy bạn nên kiểm tra bằng cách thay thế ^T6bằng ^T3và giới hạn n dưới 1000. Nhập từ stdin và đầu ra thành thiết bị xuất chuẩn.

<          Q     Slice first n
f     r2^T6      filter on range 2->10⁶
 !               Logical not (gives true if tail is empty)
  t              Tail (all but first, so gives empty if prime fact is len 1)
   PT            Prime factorization of filter var (len 1 if num is prime)

5
Từ các quy tắc: "Không được phép sử dụng các trình tạo nguyên tố tích hợp và các trình kiểm tra nguyên thủy."
Runer112

@ Runer112 Vâng, nhưng đây không phải là một thử nghiệm nguyên thủy, là yếu tố chính, nằm trên biên giới của các quy tắc. Tôi có lẽ nên hỏi nếu điều này được cho phép.
Maltysen

@Maltysen "Không được phép sử dụng các trình tạo nguyên tố tích hợp và các trình kiểm tra nguyên thủy (bao gồm các hàm thừa số nguyên tố)" - có vẻ khá rõ ràng đối với tôi.
Chấn thương kỹ thuật số

4
@DigitalTrauma việc làm rõ "(điều này bao gồm các hàm thừa số nguyên tố)" đã được thêm vào sau khi câu trả lời này được đăng.
Martin Ender

MartinBüttner Đúng. Tôi đoán tùy theo quyết định của @ ProgramFOX.
Chấn thương kỹ thuật số
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.