1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài toán giai thừa và chữ số 0

5 313 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 103,5 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Nếu ta tiếp tục xếp cột các giá trị... của L5n!. thì ta sẽ thấy chúng cũng lập thành những chuỗi 5 chữ số.

Trang 1

Trở lại bài toán tìm chữ số tận cùng khác 0 của n!

Ngô Minh Đức

Trong bài "Tối ưu các bài tóan về số nguyên tố" (THNT 10/2003), tác giả Đinh Hữu Công đã nêu ra thuật toán "Tìm chữ số tận cùng khác 0 của n!" với n<231

Trong bài này tôi xin nêu ra một cách khác giải quyết bài tóan này vô cùng nhanh chóng.

Cơ sở của nó hòan tòan từ bài viết "Tìm chữ số tận cùng khác 0 của n!" (Least

Significant Non−Zero Digit of n!) của Mathpages site

Sau đây là bài báo tiếng Anh trên đã được dịch và thay đổi một số đọan:

Gọi L(k) là chữ số tận cùng khác 0 của một số nguyên k bất kỳ Các giá trị đầu tiên của dãy L(k!) với k=2,3,4,…là:

2,6,4,2,2,4,2,8,8,8,6,8,2,8,8,6,8,2,4,4,8,4,6,4,4,8,4,6,8,…

Chúng ta sẽ tìm cách xác định giá trị của L(k!) với mọi k là số tự nhiên cho trước

Viết n! dưới dạng:

N!=2a2.3a3.5a5.7a7…

Chúng ta ký hiệu (n!)’ để chỉ số n! đã bỏ đi hết các chữ số 0 tận cùng

Ta có định lý:

Trong phân tích của n! số mũ ap của p được tính theo công thức:

Dựa vào các tính chất về phần nguyên, dễ thấy nếu p1 < p2 thì ap1≥ ap2

Vậy thì a2 ≥ a5, từ đó suy ra số mũ của 10 trong n! là a10 = a5 Bỏ đi hết các lũy thừa

của 10 trong n! ta được (n!)’:

N!’=2a2.3a3.5a5.7a7…

Dựa vào định lý trên, bạn hãy chứng minh rằng với n>2, trong phân tích của n!, ta luôn

có a2 > a5 (tức là dấu = không xảy ra) hay a2 − a5>0 Do đó (n!)’ chia hết cho 2 và L(n!)=L(n!’) sẽ nhận một trong các giá trị {2;4;6;8}

Mặt khác, ta có công thức: n!=n(n-1)!

Kết hợp hai điều này ta có thể suy ra:

L(n!)=L(L(n).L((n -1)!)) với mọi n không chia hết cho 5

Như vậy nếu đã biết được giá trị của L((5n)!) thì ta có thể tính được giá trị của L((5n+j)!)

với j=0,1,2,3,4

Các giá trị của L(n!) được xếp cột thành từng chuỗi 5 chữ số như sau:

n: 01234 5 10 15 20 25 30 35 40 45

L(n!): 01264 22428 88682 88682 44846 44846 88682 22428 22428 66264 …

(ta bỏ qua một số giá trị đặc biệt như 0!, 1! − xem như L(0!)=0)

Tuy nhiên giá trị của L((5n)!) không thực sự rõ ràng Nếu ta tiếp tục xếp cột các giá trị

Trang 2

của L((5n)!) thì ta sẽ thấy chúng cũng lập thành những chuỗi 5 chữ số Điều đó cho phép

ta nêu một kết luận tương tự: chỉ cần biết giá trị của L((25n)!) thì sẽ biết được

L((25n+5j)!) với j=0,1,2,3,4 (nghĩa là giá trị của L((25n+5j)!) chỉ phụ thuộc vào giá trị

của L((25n)!)

Tiếp tục như thế, chúng ta có thể sắp xếp các giá trị của L((5kn)!) như bảng sau:

Ta rút ra được kết luận (không thấy tác giả chứng minh): giá trị của

L((5kn+5k-1j)!) chỉ phụ thuộc vào giá trị của L((5kn)!) với j=0,1,2,3,4 Nếu giá trị của L((5kn)!) xác định được thì giá trị của L((5kn + 5k-1j)!) lập tức cũng xác định được

Ví dụ:

Ta có L((125.3)!)=L(375!)=2 và L((125.3+25)!)=L(400!)=8

Thế thì L((125.8)!)=L(1000!)=2 nên L((125.8+25)!)=L(1025)! cũng bằng 8

và L((125.10)!=L(1250!)=2 nên L((125.10+25)!)=L(1275!) cũng bằng 8)…

Tóm lại ta khẳng định nếu L((125.k)!)=2 thì chắc chắn L((125.k+25)!)phải là chữ số thứ hai trong chuỗi 28488 (chữ số 8)

Mặt khác, ta nhận thấy các giá trị của L((625n)!) giống với L(n!) Điều đó cho thấy L((5kn)!)=L((5k+4n)!) với n≠1 (không thấy tác giả chứng minh) Trên mỗi dòng ta thấy

có đúng 5 chuỗi phân biệt gồm 5 chữ số, mỗi chuỗi bắt đầu bằng một trong các số

{0,2,4,6,8} Ta chỉ cần tổng hợp tất cả các chuỗi này lại thành một bảng để sử dụng

Chúng ta rút ra được bảng sau dùng để tính giá trị của L((5kn +5k−1j)!) với j=0,1,2,3,4 khi đã biết giá trị của L((5kn)!):

Chẳng hạn nếu đã biết L((125.2)!)=8 ta tính được L((125.2+25.2)!)=6 bằng cách nhìn vào hàng (2 mod 4)=2 (do 25=52), chuỗi bắt đầu bằng chữ số 8 (82622), vị trí j=2

Thuật toán tìm L(n!)

Đổi n ra cơ số 5, ta được:

Trang 3

Dựa vào bảng trên, ta thấy nếu biết L((dn5n)!) ta sẽ tính được L((dn5n +dn-15n-1 )!) Tương tự khi biết được L((dn5n +15n-1 )!), ta sẽ tính được L((dn5n +15n-1 + dn-25n-2)!), v.v và cuối cùng sẽ tính được L(n!)

Tuy nhiên đầu tiên phải tính được L((dn5n)!), muốn vậy ta hãy hình dung:

Do đó L((dn+15n+1)!)=0(một sự quy ước cho phù hợp với bảng � để ta xét chuỗi có chữ số đầu tiên bằng 0) Ta dựa vào L((dn+15n+1)!)</I>=0 để L((dn5n)!)

Ví dụ với n=1592:

Bước 1: đổi n ra cơ số 5, được

Bước 2: Xét dòng 0 (=4 mod 4), chuỗi có chữ số đầu là 0, tức là 06264

Bước 3: chữ số đầu tiên của n (cơ số 5) là 2, do đó L((2.54)!) =2, là chữ số ở vị trí j=2 Bước 4: Xét dòng 3 (=3 mod 4), chuỗi có chữ số đầu tiên là 2, tức là 26648

Bước 5: chữ số thứ hai của n (cơ số 5) là 2, do đó L((2.54+2.53)!) =6, là chữ số ở vị trí j=2

Bước 5: Xét dòng 2 (=2 mod 4), chuỗi có chữ số đầu tiên là 6, tức là 64244

Bước 6: chữ số thứ ba của n (cơ số 5) là 3, do đó L((2.54+2.53 +3.52)!)=4 là số ở vị trí j=3

Cuối cùng ta có:

L(1592!) = L((2.54+2.53 +3.52 + 3.5 + 2)!)=4

Chúng ta mô tả bảng trên bằng cách xây dựng một mảng Ă4,5,5) Trong đó chỉ số đầu tiên cho biết vị trí dòng (0,1,2,3); chỉ số thứ hai cho biết chữ số đầu tiên của chuỗi (0,2,4,6,8); chỉ số thứ ba cho biết vị trí j (0,1,2,3,4) Nếu gọi dk là chữ số thứ k trong hệ

cơ số 5 của n, ta có thể mô tả thuật tóan ngắn gọn như sau:

Sn = Ăn mod 4, 0, dn)

Sn-1 = Ăn-1 mod 4, sn, dn-1)

S1</SUB>= Ă1,s2, d1)

S0</SUB>= s1, d0)

Cuối cùng ta có S0 = L(n!)

Chương trình:

Dữ liệu: gồm số tự nhiên n đặt trong file NONZERỌINP

Quy định: Số có thể viết trên nhiều dòng (nếu qúa dài)

vd: NONZERỌINP

549485904089340974897979878989793489787935789973493489789438957897578

478993476894845989897348

Kết qủa: in ra màn hình L(n!)

Chương trình có thể tính L((1000!)!) = 6 trong thời gian chưa tới 0.5 giây

Program Least_Significant_Non_Zero_Digit_of_f_n;

(*=============KHAI=BAO=============*)

Const InputFile=’NONZERỌINP’;

Trang 4

Const Digits: array[’0’ ’9’] of byte=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); Table:array[0 3,0 4,0 4] Of Byte=

(((0,6,2,6,4), (2,2,4,2,8), (4,4,8,4,6), (6,6,2,6,4), (8,8,6,8,2)), ((0,2,8,8,4), (2,4,6,6,8), (4,8,2,2,6), (6,2,8,8,4), (8,6,4,4,2)), ((0,4,2,4,4), (2,8,4,8,8), (4,6,8,6,6), (6,4,2,4,4), (8,2,6,2,2)), ((0,8,8,2,4), (2,6,6,4,8), (4,2,2,8,6), (6,8,8,2,4), (8,4,4,6,2))); Type BigInt= array[1 10000] of 0 9;

Var A: BigInt;

R5:BigInt;

N, N5:Word;

L: Byte;

(*==========DOC=DU=LIEU===========*) Procedure Input;

Var I:Word;

F:Text;

Ch:Char;

B:BigInt;

Begin

Assign(F,InputFile);

Reset(F);

While Not EOF(F) Do

Begin

While not EOLN(F) Do

Begin

Read(F,Ch);

N:=N+1;

B[N]:=Digits[Ch];

End;

Readln(F);

End;

Close(F);

{Mang B chua cac chu so viet xuoi: vd so=1592, B=[1,5,9,2]} {Mang A chua cac chu so viet nguoc: vd so=1592, A=[2,9,5,1]} {Ta su dung mang A cho thuan tien ve sau}

For I:=1 To N Do A[I]:=B[N-I+1];

If (N=1) And ((A[1]=0) Or (A[1]=1)) Then {0! hay 1!}

Begin

Write(1); Readln; Halt(1);

End;

End;

(*=========DOI=SANG=CO=SO=5=========*) Procedure Radix5;

Var I,J:Word; C:Byte;

Begin

C:=0;

Trang 5

N5:=0;

Repeat

N5:=N5+1;

R5[N5]:=A[N5] mod 5;

{Thay vi chia 5 ta nhan voi 2 roi chia cho 10 bang cach bo di chu so tan cung}

For I:=N5 To N Do

Begin

A[I]:=A[I]*2+C;

C:=A[I] div 10;

A[I]:=A[I] mod 10;

End;

If C=1 Then Begin

N:=N+1;

A[N]:=1;

C:=0;

End;

J:=J+1;

A[N5]:=0;

Until N5=N;

End;

(*=========TIM=CHU=SO=TAN=CUNG=KHAC=0=CUA=N!=========*) Procedure Solve;

Var S:Byte;

I:Word;

Begin

S:=0;

For I:=N5 DownTo 1 Do

S:=Table[(I-1) Mod 4,S div 2,R5[I]];

L:=S;

End;

(*=========CHUONG=TRINH=CHINH=========*)

Begin

Input;

Radix5;

Solve;

Writeln(L);

Readln;

End

Ngày đăng: 06/07/2017, 14:16

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w