Docstoc

input

Document Sample
input Powered By Docstoc
					input: số nguyên dương N (N<=20); output: số lượng ước lớn hơn 1 của giai thừa của N. ví dụ: input: 4 4!=1x2x3x4=24 các ước lớn hơn 1 của 4! là : 2,3,4,6,8,12,24 ==> output: 7 yêu cầu thời gian: 2 giây >.< bài này nếu dùng vét cạn thì tớ khoảng 11! thì bắt đầu chậm rồi. 15! thì out luôn T.T còn không dùng vét cạn thì em nghĩ hoài không ra thuật toán ( dùng đệ quy phải không nhỉ ( hay là cho vào array? TopWin May 29 2007, 03:21 PM Bạn xem bài giải này thế nào ? Mình đưa code lên trước, còn phần giải thích để ngày mai, bây giờ mình phải đi ngủ đã 3 giờ rưỡi sáng rồi (code cũng còn lộn xộn lắm! ). Bài giải này có thời gian chạy nhỏ hơn 1/18 giây. CODE {$R+} Function GT(i:integer):longint; var R:longint; j:integer; begin R:=1; For j:=2 to i do R:=R*j; GT:=R; end; Function Count(N:longint):longint; var R,i:longint; begin R:=0; For i:=2 to N div 2 do if N mod i=0 then inc(R); Count:=R+1; end; Function Count2(N:longint):longint; var TS,T:array[1..20] of integer; i,j,k,nTS:integer; i1,i2,i3,i4,i5,i6,i7,i8:integer; R:longint;

{ Function F1(i:integer):longint; var j:integer; R:longint; begin R:=0; For j:=i to nTS do R:=R+T[j]; F1:=R; end; Function F2(i:integer):longint; var j:integer; R:longint; begin R:=0; For j:=i to nTS-1 do R:=R+T[j]*F1(j+1); F2:=R; end; Function F3(i:integer):longint; var j:integer; R:longint; begin R:=0; For j:=i to nTS-2 do R:=R+T[j]*F2(j+1); F3:=R; end; Function F4(i:integer):longint; var j:integer; R:longint; begin R:=0; For j:=i to nTS-3 do R:=R+T[j]*F3(j+1); F4:=R; end; Function F5(i:integer):longint; var j:integer; R:longint; begin R:=0; For j:=i to nTS-4 do R:=R+T[j]*F4(j+1); F5:=R; end; Function F6(i:integer):longint;

var j:integer; R:longint; begin R:=0; For j:=i to nTS-5 do R:=R+T[j]*F5(j+1); F6:=R; end; Function F7(i:integer):longint; var j:integer; R:longint; begin R:=0; For j:=i to nTS-6 do R:=R+T[j]*F6(j+1); F7:=R; end; Function F8(i:integer):longint; var j:integer; R:longint; begin R:=0; For j:=i to nTS-7 do R:=R+T[j]*F7(j+1); F8:=R; end;} Function F(n,i:integer):longint; var j:integer; R:longint; begin R:=0; if n=1 then begin For j:=i to nTS do R:=R+T[j]; F:=R; exit; end; For j:=i to nTS-n+1 do R:=R+T[j]*F(n-1,j+1); F:=R; end; begin FillChar(TS,sizeof(TS),0); FillChar(T,sizeof(T),0); For k:=2 to N do

begin i:=2; j:=k; While j>1 do begin if j mod i =0 then begin inc(TS[i]); j:=j div i; end else inc(i); end; end; R:=0; nTS:=0; For i:=2 to 20 do if TS[i]<>0 then begin inc(nTS); T[nTS]:=TS[i]; end; { For i1:=1 to nTS do R:=R+T[i1]; For i1:=1 to nTS-1 do For i2:=i1+1 to nTS do R:=R+T[i1]*T[i2]; For i1:=1 to nTS-2 do For i2:=i1+1 to nTS-1 do For i3:=i2+1 to nTS do R:=R+T[i1]*T[i2]*T[i3]; For i1:=1 to nTS-3 do For i2:=i1+1 to nTS-2 do For i3:=i2+1 to nTS-1 do For i4:=i3+1 to nTS do R:=R+T[i1]*T[i2]*T[i3]*T[i4]; For i1:=1 to nTS-4 do For i2:=i1+1 to nTS-3 do For i3:=i2+1 to nTS-2 do For i4:=i3+1 to nTS-1 do For i5:=i4+1 to nTS do R:=R+T[i1]*T[i2]*T[i3]*T[i4]*T[i5]; For i1:=1 to nTS-5 do For i2:=i1+1 to nTS-4 do For i3:=i2+1 to nTS-3 do For i4:=i3+1 to nTS-2 do For i5:=i4+1 to nTS-1 do

For i6:=i5+1 to nTS do R:=R+T[i1]*T[i2]*T[i3]*T[i4]*T[i5]*T[i6]; For i1:=1 to nTS-6 do For i2:=i1+1 to nTS-5 do For i3:=i2+1 to nTS-4 do For i4:=i3+1 to nTS-3 do For i5:=i4+1 to nTS-2 do For i6:=i5+1 to nTS-1 do For i7:=i6+1 to nTS do R:=R+T[i1]*T[i2]*T[i3]*T[i4]*T[i5]*T[i6]*T[i7]; For i1:=1 to nTS-7 do For i2:=i1+1 to nTS-6 do For i3:=i2+1 to nTS-5 do For i4:=i3+1 to nTS-4 do For i5:=i4+1 to nTS-3 do For i6:=i5+1 to nTS-2 do For i7:=i6+1 to nTS-1 do For i8:=i7+1 to nTS do R:=R+T[i1]*T[i2]*T[i3]*T[i4]*T[i5]*T[i6]*T[i7]*T[i8]; } { R:=F1(1)+F2(1)+F3(1)+F4(1)+F5(1)+F6(1)+F7(1)+F8(1);} R:=F(1,1)+F(2,1)+F(3,1)+F(4,1)+F(5,1)+F(6,1)+F(7,1)+F(8,1); Count2:=R; end; Var n:integer; T:longint absolute $0:$046C; T1:longint; BEGIN Writeln; Write('n= '); readln(n); Writeln('n! = ',GT(n)); if n<12 then begin T1:=T; Writeln('So uoc so cua n! la (vet can): ',Count(GT(n)),'.'); Writeln('Time = ', (T-T1)/18.2:0:2,'s.'); end; T1:=T; Writeln('So uoc so cua n! la ',Count2(n),'.'); Writeln('Time = ', (T-T1)/18.2:0:2,'s.'); END. bocaumatkieng May 30 2007, 09:22 AM eo ơi. 3 giờ rưỡi sáng mà bạn vẫn đủ tỉnh táo để gõ đoạn code dài thế kia...bái phục bái phục...mình sẽ xem lại xem, nếu hiểu thì thật là mừng còn nếu không hiểu chắc lại

phải cầu cứu bạn wá. tạm thời tình hình đang gay go, vì máy tính nhà mình bị virus hư mất rồi, phải wa nhà chú mượn máy tính để coi đây nè dù bạn có rảnh thời gian để giải thích hay không, cũng cảm ơn bạn nhìu nhìu nhé [hug hug] TopWin May 30 2007, 01:17 PM Ý tưởng của mình là: phần tích N! ra tích các thừa số nguyên tố bằng cách phân tích 2,3,4,5,...,n ra thừa số nguyên tố. Ví dụ 4! có các thừa số nguyên tố sau 23 và 3. Dễ dàng ta thấy rằng mỗi ước số sẽ tương ứng với một cách kết hợp của một vài thừa số nguyên tố trên. 2=2. 3=3. 4=2x2. 6=3x2. 8=2x2x2. 12=2x2x3. 24=2x2x2x3. Như vậy số ước số (tức là đáp án cần tìm) chính là số cách kết hợp được. Bây giờ công việc của ta là phải tính cho được số cách kết hợp. Nếu coi các thừa số nguyên tố là một tập hợp, trong ví dụ trên là tập {2,2,2,3} thì số cách kết hợp nói trên là số tập hợp con không trùng nhau của tập trên. Lưu ý là không trùng nhau. Xét các tập con chỉ có "một loại thừa số" (trong ví dụ trên là hoặc chỉ có 2 hoặc chỉ có 3, số lượng 2 và 3 không để ý), số các tập hợp loại này chính là tổng các số mũ của mỗi loại thừa số nguyên tố. Trong ví dụ trên là 3+1. 3 là 23 và 1 là 31. Bây giờ xét các tập con có chứa đúng "2 loại thừa số", nó sẽ là "tổng của tất cả các tích 2 số mũ của 2 loại bất kì". Nghe có vẻ khó hiểu nhỉ. Lấy ví dụ nếu bạn phần tích ra có 3 loại thừa số là 2x, 3y và 5z thì số tập con lúc này là x*y + y*z + x*z. Nếu có 4 loại 2x, 3y, 5z và 7t thì số tập con là x*y + x*z + x*t +y*z + y*t + z*t. Nói nôm na là cứ lấy tích các bộ 2 số mũ, rồi tính tổng của chúng. Tương tự các tập con có 3,4...n loại thừa số thì cứ lấy tích các bộ 2,3...n số mũ, rồi tính tổng của chúng. Vậy số tập con (cũng chính là kết quả) là tổng của số tập con có 1 loại, 2 loại,...n loại thừa số nguyên tố (tức là tổng của tất cả các tổng trên!). Bởi vậy trong code có một đoạn dài các vòng for lồng nhau (tui để trong dấu móc {}). Tui viết vậy cho dễ hiểu và tương ứng với cách giải thích trên, đoạn mã có n vòng for lồng nhau tương ứng với việc tính số tập con có n loại thừa số nguyên tố. Có lẽ bạn sẽ hỏi là viết như vậy thì phải viết bao nhiêu vòng for lồng nhau mới đủ vì ta đâu có biết n! sẽ có tối đa bao nhiêu loại thừa số nguyên tố ? Cách giải quyết thứ nhất là chuyển sang viết hàm đệ quy (là Function Fn trong code đó). Đây là cách giải quyết tốt nhất nhưng không phải duy nhất. Cách giải quyết thứ 2: trong code không phải ngẫu nhiên tôi viết đến 8 vòng for lồng nhau rồi dừng lại, bởi vì trong đề bài người ta cho n<=20 suy ra các thừa số nguyên tố cũng phải nhỏ hơn 20, mà nhỏ hơn 20 thì chỉ có 8 số nguyên tố là 2,3,5,7,11,13,17,19 mà thôi. Nếu đi thi chắc tôi sẽ dùng cách 2 vì nói chắc chắn và không phải suy nghĩ nhiều như khi viết đệ quy. Một lời khuyên cho bạn khi đi thi là khi đọc xong một đề tin, hãy khoan nghĩ đến các

cách giải mà các sách tin học thường đề cập đến, mà hãy nghĩ đến các kiến thức toán học mà mình đã học trước đó đã. Các sách tin học thường làm nổi bật các phương pháp giải trong tin (vì đó là sách tin) mà quên rằng tin bắt nguồn từ toán. Nhưng bạn thấy đó cách giải quyết 1 là kiểu tin, cách giải quyết 2 là kiểu toán dễ hiểu hơn nhiều (là điều cần thiết trong khi thi). Bởi vậy trước khi thi đừng quên đọc lại các kiến thức toán học đặc biệt là phần số học. Chúc bạn thi tốt! TopWin May 30 2007, 01:18 PM À quên,nếu bạn có ý định cám ơn thì hãy post thật nhiều các đề tin mà bạn có được để diễn đàn thêm sôi động và tôi cũng có dịp rèn luyện thêm. QuocHeo May 30 2007, 09:06 PM QUOTE(TopWin @ May 31 2007, 01:17 AM) Bây giờ xét các tập con có chứa đúng "2 loại thừa số", nó sẽ là "tổng của tất cả các tích 2 số mũ của 2 loại bất kì". Nghe có vẻ khó hiểu nhỉ. Lấy ví dụ nếu bạn phần tích ra có 3 loại thừa số là 2x, 3y và 5z thì số tập con lúc này là x*y + y*z + x*z. Nếu có 4 loại 2x, 3y, 5z và 7t thì số tập con là x*y + x*z + x*t +y*z + y*t + z*t. Nói nôm na là cứ lấy tích các bộ 2 số mũ, rồi tính tổng của chúng. Một lời khuyên cho bạn khi đi thi là khi đọc xong một đề tin, hãy khoan nghĩ đến các cách giải mà các sách tin học thường đề cập đến, mà hãy nghĩ đến các kiến thức toán học mà mình đã học trước đó đã. Các sách tin học thường làm nổi bật các phương pháp giải trong tin (vì đó là sách tin) mà quên rằng tin bắt nguồn từ toán. Nhưng bạn thấy đó cách giải quyết 1 là kiểu tin, cách giải quyết 2 là kiểu toán dễ hiểu hơn nhiều (là điều cần thiết trong khi thi). Bởi vậy trước khi thi đừng quên đọc lại các kiến thức toán học đặc biệt là phần số học. Chúc bạn thi tốt! lời khuyên là đúng, nhưng mà cái tính tổng ở phía trên, mình học toán 12 năm nay, chưa bao giờ thấy cái cách tính tổng này, bạn lấy nguồn ở đâu vậy :|, nếu như có thì sẽ rất bổ ích đấy TopWin May 30 2007, 11:41 PM QUOTE nhưng mà cái tính tổng ở phía trên, mình học toán 12 năm nay, chưa bao giờ thấy cái cách tính tổng này, bạn lấy nguồn ở đâu vậy :|, nếu như có thì sẽ rất bổ ích đấy Làm gì có, tự suy luận từ kiến thức số học & tổ hợp thôi. Thế này nhé: giả sử có hai loại thừa số nguyên tố 2x và 3y, các tập con chứa hai loại này sẽ có dạng {2i, 3j} trong đó i Є {1,2,...,x} và j Є {1,2,...,y}. Theo như hồi lớp 6 (hình như thế) thì i có x cách chọn, j có y cách chọn suy ra số tập con tìm được là x*y..