Kiểm tra xem một số có phải là tích của các số nguyên liên tiếp không


18

Một số số như: 6, 12, 20, 30, 42, 56, 60, 90, 120, v.v ... có thể được biểu thị dưới dạng tích của các số nguyên liên tiếp như hình dưới đây.

6   = 2 * 3  
12  = 3 * 4  
30  = 5 * 6
60  = 3 * 4 * 5  
90  = 9 * 10  
120 = 4 * 5 * 6  

Viết chương trình hoặc hàm xuất ra danh sách các số nguyên liên tiếp mà sản phẩm bằng với số được chỉ định.

Ví dụ về các số không phù hợp với logic này là:

99  = 9 * 11  (Product of non-consecutive numbers)
121 = 11 * 11 (Same numbers)
2   = 1 * 2   (Product of itself and 1)
13  = 13      (Product of only one number)

Xin lưu ý rằng trong trường hợp 2 = 2 * 1, chúng tôi không coi đó là kết quả hợp lệ, vì một số nguyên nhân với 1 cho kết quả tương tự. Đối với câu hỏi này, chúng tôi sẽ chỉ xem xét các số nguyên> = 2 trong sản phẩm.

Đầu vào

Một số nguyên dương 32 bit hợp lệ. Có thể từ đầu vào tiêu chuẩn, một đối số chức năng, vv

Đầu ra

Danh sách các số nguyên liên tiếp> = 2 (theo thứ tự tăng dần hoặc giảm dần). Nếu có một số kết hợp các số nguyên liên tiếp, chỉ cần cung cấp một trường hợp sẽ làm. Nếu bạn cung cấp nhiều hơn, nó tốt.

Những hạn chế

Mã phải mất một khoảng thời gian hợp lý (<5 phút) để chạy trên máy tính tiêu chuẩn cho tất cả các đầu vào hợp lệ (số nguyên 32 bit dương). Nếu có một sản phẩm số nguyên liên tiếp, mã sẽ xuất một hoặc nhiều trong thời gian giới hạn. Khác, mã nên chấm dứt không có đầu ra trong thời gian giới hạn.

Đây là mã golf, vì vậy mã ngắn nhất tính bằng byte sẽ thắng.


1
Câu đố này, như đã nêu, không phù hợp với định dạng của trang web này. Trang web này dành cho các cuộc thi trong đó có một cách hay để quyết định người chiến thắng (ví dụ: mã ngắn nhất, mã nhanh nhất, hầu hết các upvote, v.v.). Bạn đã không cung cấp bất kỳ cách nào như vậy.
Chris Jester-Young

2
Tôi khuyên bạn nên biến nó thành một môn đánh gôn (mã ngắn nhất.) Bạn cần đặt một số giới hạn cho nó. Ví dụ: các số từ 0 đến 1000000, thời gian thực hiện tối đa 10 giây, v.v.
Level River St

Đã cố gắng để chỉnh sửa nó để cứu vãn câu hỏi này. Nhưng tôi chưa đưa ra bất kỳ câu hỏi nào trước đây, vì vậy nếu bạn thấy bất cứ điều gì, xin vui lòng chỉnh sửa.
Vectorized

@bitpwner Ngoài vài lỗi chính tả, có vẻ tốt với tôi. Bình chọn để mở lại.
xem

5
Tôi nghĩ bạn có ý nghĩa 30=5*6.
Kyle Kanos

Câu trả lời:


8

Java - 124

String f(int t){int s=2,h=3,p=s,i;String o="";for(;p!=t&&s*s<t;p=p<t?p*h++:p/s++);if(p==t)for(i=s;i<h;o+++=i+" ");return o;}

Bắt đầu từ 2, vòng lặp này cho đến khi số bắt đầu là> căn bậc hai của mục tiêu (hoặc mục tiêu được đạt chính xác). Nếu sản phẩm thấp, nó nhân với số cao và tăng nó. Nếu cao, nó chia cho số bắt đầu và tăng nó.

Ví dụ: trong 30, nó sẽ kiểm tra:

2*3     = 6 (too low, multiply)
2*3*4   = 24 (too low, multiply)
2*3*4*5 = 120 (too high, divide)
3*4*5   = 60 (too high, divide)
4*5     = 20 (too low, multiply)
4*5*6   = 120 (too high, divide)
5*6     = 30 (bingo!)

Xuất ra một chuỗi các yếu tố được phân tách bằng dấu cách theo thứ tự tăng dần.

Với ngắt dòng:

String p(int t){
    int s=2,h=3,p=s,i;
    String o="";
    for(;p!=t&&s*s<t;p=p<t?p*h++:p/s++);
    if(p==t)
        for(i=s;i<h;o+=i+" ");
    return o;
}

7

Python - 104 97 95 92 hãy thử nó

n=input()
s=i=2
c=1
while s<n:
 s*=i+c;c+=1
 if s==n:print range(i,i+c)
 if s/n:i+=1;s,c=i,1

Nếu n, ví dụ, được đặt thành 120 trước, chương trình sẽ đưa ra hai giải pháp:

[2, 3, 4, 5]
[4, 5, 6]

Xin lỗi, tôi quên xác định một số đầu vào.
Falko

1
thay c = c + 1, i = i + 1 bằng c + = 1, i + = 1
Gerrat

1
Ồ vâng, đã không nghĩ về +=. Nhưng tôi nhớ ++trong Python ...
Falko

1
if s>=nif s/ntương đương nhau, vì vậy bạn có thể cung cấp tất cả các giải pháp trong cùng một số ký tự.
isaacg

1
Bạn có thể lưu ba ký tự bằng cách thay đổi s=s*(i+c)thành s*=i+c.
El'endia Starman

4

Clojure - 127 109 byte

(defn f[x](first(for[r[range]y(r 2 x)v[(take-while #(<=(apply * %(r y %))x)(r y x))]:when(=(apply * v)x)]v)))

Thí dụ:

(map f [6 12 30 60 90 120 1404816 99 121 2 13])
=> ((2 3) (3 4) (5 6) (3 4 5) (9 10) (2 3 4 5) (111 112 113) nil nil nil nil)

Giải trình:

Đây là cách tiếp cận chức năng khá cơ bản, không tối ưu. Tôi tạo một danh sách lười biếng về tất cả các khả năng bằng cách sử dụng một vòng lặp đơn giản trên chúng (nó bỏ qua tất cả các kết hợp sẽ cho số lượng quá lớn, ngăn chặn tràn) và lấy đầu tiên của chúng. Nếu không có khả năng tồn tại, nó sẽ trả về con số không.

Dễ nhất để kiểm tra trong http://tryclj.com/ .


Bây giờ tôi cũng nhận thấy rằng tôi có thể trả về tất cả các khả năng: 120 byte 102 byte , nhưng cho kết quả trong một danh sách lồng nhau.

(defn f[x](for[r[range]y(r 2 x)v[(take-while #(<=(apply * %(r y %))x)(r y x))]:when(=(apply * v)x)]v))

Thí dụ:

(map f [6 12 30 60 90 120 1404816 99 121 2 13])
=> (((2 3)) ((3 4)) ((5 6)) ((3 4 5)) ((9 10)) ((2 3 4 5) (4 5 6)) ((111 112 113)) () () () ())

3

CJam, 31 byte

q~:Qmq,A,m*{2f+~,f+_:*Q={p}*}%;

Đó là một cách tiếp cận mạnh mẽ, nhưng thời gian thực hiện chỉ mất vài giây khi sử dụng trình thông dịch Java chính thức .

Nếu bạn muốn kiểm tra mã bằng trình thông dịch trực tuyến , bạn nên giữ đầu vào ở mức thấp hợp lý. Bất cứ điều gì ít hơn 2 26 vẫn hoạt động trên máy của tôi.

Ví dụ

$ TIME="%e s"
$ time cjam product.cjam <<< 2
0.12 s
$ time cjam product.cjam <<< 6
[2 3]
0.10 s
$ time cjam product.cjam <<< 120
[2 3 4 5]
[4 5 6]
0.12 s
$ time cjam product.cjam <<< 479001600
[2 3 4 5 6 7 8 9 10 11 12]
0.68 s
$ time cjam product.cjam <<< 4294901760
[65535 65536]
1.48 s
$ time cjam product.cjam <<< 4294967295
1.40 s

Làm thế nào nó hoạt động

q~:Q      " Read from STDIN, interpret the input and save the result in variable “Q”.     ";
mq,       " Push the array [ 0 1 2 … (Q ** 0.5 - 1) ].                                    ";
A,m*      " Push the array [ 0 1 2 … 9 ] and take the Cartesian product.                  ";
{         " For each pair in the Cartesian product:                                       ";
  2f+     " Add 2 to each component.                                                      ";
  ~       " Dump the array's elements on the stack.                                       ";
  ,       " Push the array [ 0 1 2 … n ], where “n” is the topmost integer on the stack.  ";
  f+      " Add “m” to each element, where “m” is the integer below the array.            ";
  _:*     " Duplicate the resulting array and push the product of its elements.           ";
  Q={p}*  " If the product is equal to “Q”, print.                                        ";
}%        " Collect the remaining results into an array.                                  ";
;         " Discard the array from the stack.                                             ";

2

Java, 162

trả về một mảng các số nguyên hoặc nullnếu không có số liên tiếp tồn tại.

int[] e(int n){for(int i=1;i<n;i++){int h=i+1,c=1,s=i;while(s<n){c++;s*=h++;}if(s==n){int[] o=new int[c];for(int j=0;j<c;j++){o[j]=h-j-1;}return o;}}return null;}

vô dụng:

int[] execute(int input){
    for(int i=1; i<input; i++){
        int highest = i+1, count = 1, sum = i;
        while(sum < input){
            count++;
            sum *= highest++;
        }
        if(sum == input){
            int[] numbers = new int[count];
            for(int j=0; j<count; j++){
                numbers[j] = highest-j-1;
            }
            return numbers;
        }
    }
    return null;
}

2

C 105 110 hãy thử nó

n,k,l;main(i){for(scanf("%d",&n);++i<n;)for(k=1,l=i;k<n;)if(k*=l++,k==n)for(l=n;l/=i;)printf("%d ",i++);}

144 có thưởng: cái này lặp lại qua mỗi số và tìm sản phẩm phù hợp

main(i,j,k,l,m){for(scanf("%d",&m);++i<13;)for(j=0;++j<46341-i;){for(l=k=1;k<=i;)l*=j+k++;if(l==m)for(puts(""),k=0;k<i;)printf("%d ",j+k+++1);}}

Đẹp, rất đơn giản và thanh lịch! Chắc chắn làm việc cho một số con số nhỏ hơn mà tôi đã ném vào nó. Sau đó, tôi đã đưa cho nó 50815512 (7128 x 7129) và nó đã đi vào một vòng lặp vô hạn. Có phải nó tràn ra khi nó cố gắng tính toán 7128 x 7129 x 7130 = 362314600560?
Todd Lehman

cảm ơn! Rõ ràng là điều kiện k < nđi quá cao vì k *= l++. tôi có thể nối thêm unsigned long dài đến đầu nhưng ... đó sẽ hủy hoại cuộc sống
bebe

2

PHP ký tự 258, 201 không tính chức năng giai thừa.

Cách đơn giản nhất để bày tỏ về mặt toán học "yếu tố liên tiếp bằng một số" là X!/Y!ở đâu Xlà số cao nhất và Ylà một trong những trừ thấp nhất. Thật không may, tôi đã ngừng tính toán trước khi tôi học cách giải Z = X!/Y!, vì vậy tôi phải đánh giá nó một chút.

Phiên bản lộn xộn, vô dụng:

<?php
// PHP does not define a factorial function, so I've kludged one in.
function fact($n) {
    $r = 1;
    for($i=$n; $i>1; $i--) {
        $r *= $i;
    }
    return $r;
}

$input = intval($argv[1]);

if( $input < 2 ) { die('invalid input'); }

printf("input: %s\n", $input);

$max=min(ceil(sqrt($input)),170); // integer breakdown for > 170!
$grid = array();
for( $x=1;$x<$max;$x++ ) {
    for( $y=$max;$y>=1;$y-- ) {
        if( $y >= $x ) { continue; } // Skip results that would be < 1
        $cur = fact($x)/fact($y);
        if( $cur > $input ) { // too large!
            echo "\n"; continue 2;
        }
        if( $cur == $input ) { //just right
            printf("%7d\n\nFound %s == %s\n", $cur, implode(' * ', range($y+1, $x)), $cur);
            break 2;
        }
        printf("%7d ", $cur);
    }
    echo "\n";
}
if($cur!=$input){printf("No consecutive factors produce %d\n", $input);}

Ví dụ đầu ra:

input: 518918400

  2
  3       6
  4      12      24
  5      20      60     120
  6      30     120     360     720
  7      42     210     840    2520    5040
  8      56     336    1680    6720   20160   40320
  9      72     504    3024   15120   60480  181440  362880
 10      90     720    5040   30240  151200  604800 1814400 3628800
 11     110     990    7920   55440  332640 1663200 6652800 19958400 39916800
 12     132    1320   11880   95040  665280 3991680 19958400 79833600 239500800 479001600
 13     156    1716   17160  154440 1235520 8648640 51891840 259459200
 14     182    2184   24024  240240 2162160 17297280 121080960
 15     210    2730   32760  360360 3603600 32432400 259459200
 16     240    3360   43680  524160 5765760 57657600 518918400

Found 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 == 518918400

Chơi gôn

<? function f($n){$r=1;for($i=$n;$i>1;$i--)$r*=$i;return $r;}$i=$argv[1];$m=min(ceil(sqrt($i)),170);for($x=1;$x<$m;$x++){for($y=$m;$y>0;$y--){if($y>=$x)continue;$c=f($x)/f($y);if($c>$i)continue 2;if($c==$i){$y++;echo "$y $x";break 2;}}}if($c!=$i){echo 'No';}

Đầu ra:

[sammitch@vm ~/golf] time php consecutive_golf.php 518918400
9 16
real 0m0.019s
user 0m0.011s
sys  0m0.009s
[sammitch@vm ~/golf] time php consecutive_golf.php 518918401
No
real 0m0.027s
user 0m0.017s
sys  0m0.011s

Tôi không mong đợi thời gian chạy sẽ khá nhanh như vậy!


ý tưởng này cũng xuất hiện trong đầu tôi và nó có vẻ rất hiệu quả nhưng tôi nghi ngờ nó có thể được rút ngắn đủ để "đủ điều kiện".
bebe

1
@bebe đó là 258 ký tự, không quá tệ đối với PHP. Nếu tôi không lười biếng và cố chấp, tôi sẽ làm điều đó bằng một ngôn ngữ thực sự . : P
Sammitch

X! / Y! là tích của số nguyên N sao cho Y <N <= X. Điều đó có giúp ích gì không?
trichoplax

2

Bình thường , 35

JvwKr2 4W-ZJ~@KgJZ1=YurGHK=Zu*NTY)Y

Ghi chú: Mã của tôi thực sự tìm thấy đại diện ngắn nhất của đầu vào dưới dạng đại diện cho các số nguyên liên tiếp> = 2, vì vậy, với đầu vào không hợp lệ, nó sẽ in danh sách 1 phần tử, có thể sau một thời gian rất dài. Vì báo cáo vấn đề cho biết đầu vào sẽ hợp lệ, tôi cho rằng điều này là ổn.

Giải thích ngắn gọn:

Về cơ bản, chương trình lưu trữ giới hạn trên và dưới của một phạm vi, tính toán tích của các số trong phạm vi bằng cách sử dụng mức giảm, điều chỉnh các điểm cuối khi cần thiết và lặp lại cho đến khi sản phẩm bằng với đầu vào.

Giải thích dài dòng:

Đối với mỗi đoạn mã, tôi sẽ đưa ra con trăn tương đương, cũng như một lời giải thích và lý luận chi tiết hơn.

Jvw => J=eval(input())

Cách tiêu chuẩn để lấy đầu vào trong Pyth.

Kr2 4 => K=range(2,4)=>K=[2,3]

Đây là phần kỳ lạ đầu tiên: Thay vì lưu trữ các điểm cuối dưới dạng các biến riêng biệt, tôi đang lưu trữ chúng dưới dạng các thành phần của danh sách. Lý do sẽ sớm được rõ ràng. Ngoài ra, thay vì thực hiện một nhiệm vụ đơn giản, trong Pyth sẽ làK[2 3) , tôi đang sử dụng một phạm vi để lưu một ký tự.

W-ZJ=> while Z-J=>while Z!=J

Tại thời điểm này, bạn có thể hỏi, "Z là gì? Bạn chưa định nghĩa nó." Trong Pyth, tất cả các biến được xác định trước. Z xảy ra bắt đầu là 0. Tuy nhiên, Z sẽ được đặt thành giá trị của sản phẩm sau đó, vì vậy kiểm tra này sẽ phục vụ để kết thúc vòng lặp while khi danh sách ở giá trị chính xác.

~@K>JZ1 => K[J>Z] += 1

Đây là lý do tại sao tôi lưu trữ các giá trị trong một danh sách, không phải trong các biến riêng biệt: Tôi muốn tăng một trong hai điểm cuối, tùy thuộc vào việc sản phẩm hiện tại quá cao hay quá thấp. Đó sẽ là một điều kiện khá dài nếu các điểm cuối là các biến riêng biệt, nhưng với phép thuật lập chỉ mục danh sách, nó trở nên ngắn. Ngoài ra, thực tế là kiểm tra này xuất hiện trước sản phẩm và thực tế là Z được khởi tạo thành 0, đảm bảo rằng K sẽ[2,4] ở lần đầu tiên chúng tôi lấy sản phẩm, đó là điểm cuối thích hợp.

=YurGHK=> Y=reduce(lambda G,H: range(G,H),K)=>Y=range(K[0],K[1])

Bây giờ, tôi cần danh sách thực tế rằng sản phẩm sẽ được tiếp quản, và nó sẽ được in ra nếu chúng tôi thành công. Rõ ràng, chúng tôi sẽ sử dụng một chức năng phạm vi. Sự khó khăn nằm ở việc có được các đầu vào cho hàm phạm vi. Cách rõ ràng để làm điều này, bằng cách lập chỉ mục danh sách, sẽ là =Yr'K@K1. Tuy nhiên, bằng cách sử dụng hàm giảm trong danh sách hai phần tử này, chúng ta có thể rút ngắn nó bằng một ký tự.

=Zu*NTY => Z=reduce(lambda N,T: N*T,Y)

Và bây giờ, đối với toàn bộ vấn đề này, việc giảm hoạt động để tìm sản phẩm của danh sách.

) => Kết thúc trong khi

Y => print(Y)

Khi thành công, in danh sách.

Chạy ví dụ:

$ cat seq_prod 
JvwKr2 4W-ZJ~@K>JZ1=YurGHK=Zu*NTY)Y

$ cat seq_prod | python3 pyth.py
<debug stuff>
==================================================
[9, 10, 11, 12, 13, 14, 15, 16]

1

Java - 115

void f(int i){for(int j=2;j<i;j++)for(int k=1,x=j;(x*=j+k)<i;k++);if(x==i)for(i=j;i<j+k;i++)System.out.println(i);}

Hơi ít chơi golf:

void f(int i) {
 for(int j=2; j<i; j++)
  for(int k=1, x=j; (x*=j+k) < i; k++);
   if(x == i)
    for(i=j; i<j+k; i++)
     System.out.println(i);
}

Eh, bạn đã tạo một hàm và in giá trị trả về. Chưa từng thấy điều đó được thực hiện ở đây trước đây.
xem

Tôi không thể lấy nó để in bất cứ thứ gì ... Nhưng nếu nó mang lại cho tôi một số đầu ra, bạn có thể đánh golf System.out.printlnxuống System.out.printvà dấu chấm phẩy ở cuối for(int k=1,x=j;(x*=j+k)<i;k++)không chỉ không cần thiết mà còn gây ra lỗi.
Qwix

Điều này không làm việc cho tôi. x, j, kLà ra khỏi phạm vi ở cuối cùng if/forkhối vì một ;. Nếu tôi loại bỏ ;, nó không in bất cứ điều gì.
Geobits

1
@Qwix Thay đổi thành printcó nghĩa là anh ta cần thêm một ký tự khoảng trắng để tránh các số chạy cùng nhau.
Geobits

1
@Geobits Điểm tốt! Tôi có lẽ đã thấy rằng nếu nó đã cho tôi một số đầu ra.
Qwix

1

Matlab (88)

Mã dự kiến ​​số sẽ được lưu trữ trong xvà đầu ra l.

for n=2:12
r=ceil(x^(1/n))
for s=-3*n:n
l=r-s+(1:n)
if prod(l)==x
return 
end;end;l=x;end

13! > 2^32mã này chỉ tìm kiếm các sản phẩm có độ dài 2 lên đến 12. Mã này có thời gian chạy liên tục khoảng 0,001 giây.


1

Scala - 86

def p(n:Int)=(2 to n).flatMap(i=>(i to n).map(i to _-1).find(_.product==n)).headOption

Mã này rất không hiệu quả nhưng tối ưu hóa nó sẽ chỉ thêm một vài ký tự. Nó sử dụng một cách tiếp cận chức năng để kiểm tra các sản phẩm của tất cả các chuỗi liên tiếp có thể. (một chuỗi số nguyên liên tiếp được biểu diễn dưới dạng đối tượng Phạm vi trong Scala)

vô dụng:

def product(n: Int): Option[Range] = {
  def productStartingAt(start: Int): Option[Range] =
    (start to n-1).map(start to _).find(_.product == n)

  (2 to n).flatMap(i => productStartingAt(i)).headOption
}

1

Hiện tại, CJam không hoạt động với số lượng lớn do thời gian tính toán dài

Đây là mã CJam ngắn nhất của tôi. Kiểm tra tại http://cjam.aditsu.net/ . Nó hoạt động bằng cách: xác định đầu vào là A; tạo một mảng gồm tất cả các số từ 0 đến A-1; Đá 0; đá các số nhỏ nhất cho đến khi nhân tất cả các số trong mảng không lớn hơn A; kiểm tra nếu nó lớn hơn A; nếu không, tạo một mảng từ 0 đến A-2; và lặp lại cho đến khi câu trả lời được tìm thấy. Nếu không tìm thấy, một ngoại lệ được ném ra. Tôi đã không nghĩ rằng khoảng trắng giữa các số là cần thiết để chúng được nhập vào mã thứ hai dài 32 ký tự.

ri:A,{)\;,1{;(;_{*}*_A>}gA<}g

ri:A,{)\;,1{;(;_{*}*_A>}gA<}g" "*

Tôi nghĩ rằng câu trả lời của bạn là quá chậm để có hiệu lực. Hãy nhớ rằng, nó phải hoàn thành không quá 5 phút trên bất kỳ số nguyên 32 bit hợp lệ nào. Mất bao lâu trên 3600060000 == 60000 * 60001?
isaacg

điểm công bằng, tôi sẽ làm lại và đăng nếu nó ngắn
kaine

Nếu bạn sẽ làm lại nó, vui lòng xóa câu trả lời này cho đến khi đó, hoặc bằng cách nào đó chỉ ra rằng hiện tại không hợp lệ.
isaacg

1

Phi tiêu - 102 ký tự

Đây là một thực hiện chậm. Nó có thể được thực hiện nhanh hơn nhưng điều đó đòi hỏi nhiều ký tự hơn (như chỉ thực hiện vòng lặp cho đến khii*i<n )

f(n,[i=2]){
  t(j,p,a)=>p<n?t(++j,p*j,a..add(j)):p>n?f(n,i+1):a;
  for(;i<n;i++)if(n%i<1)return t(i,i,[i]);
}

(102 ký tự không có ngắt dòng và khoảng trắng hàng đầu).

Để sử dụng nó, hãy làm một cái gì đó như:

main() {
  print(f(123456789*123456790));
}

0

Javascript, 88

Mã đánh gôn:

function f(a){for(i=2;i<a;i++){b=[1];for(j=i;j>1;j--)if((b[0]*=b[i-j+1]=j)==a)alert(b)}}

Mã dễ đọc hơn (cách đều nhau):

function f(a){
    for(i=2;i<a;i++){
        b=[1];
        for(j=i;j>1;j--)
            if((b[0]*=b[i-j+1]=j)==a)
                alert(b);
    }
}

Với mỗi số từ 2 đến số đầu vào, nó tìm sản phẩm của các số nguyên liên tiếp từ số hiện tại trở về 2. Nếu sản phẩm này bằng số đầu vào, thì dãy số liên tiếp, cùng với số đầu vào ban đầu, là đầu ra .

Nó xuất ra số đầu vào theo sau là các số nguyên liên tiếp có sản phẩm là số đầu vào.

Ví dụ f (120) tạo ra một cảnh báo với văn bản "120,5,4,3,2" và sau đó là cảnh báo thứ hai với văn bản "120,6,5,4".

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.