求n的阶乘最后一位非0数字的问题。请人分析pascal代码

题目:
第2题 阶乘问题(fact.pas/in/out)

也许你早就知道阶乘的含义,N阶乘是由1到N相乘而产生,如:
12! = 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 = 479,001,600
12的阶乘最右边的非零位为6。
写一个程序,计算N(1<=N<=50,000,000)阶乘的最右边的非零位的值。
注意:10,000,000!有2499999个零。

输入
仅一行包含一个正整数N。

输出
单独一行包含一个整数表示最右边的非零位的值。

样例
fact.in
12

fact.out
6

分析代码
第1个
program fact;
const
data:array [0..3] of 0..9=(8,4,2,6);
var
i,ans,a,b,c,n,f:longint;
procedure init;
begin
assign(input,'fact.in');reset(input);
assign(output,'fact.out');rewrite(output);
readln(n);
end;

procedure doit;
begin
b:=1; a:=n div 10; b:=a mod 4;
if a<=100 then b:=data[b-1];
if a>=1000000 then b:=data[b-2];
if (a>100) and (a<1000000) then b:=data[b];
c:=n mod 10; f:=1;
for i:=1 to c do f:=f*i;
f:=f*b;
while f mod 10=0 do f:=f div 10;
ans:=f mod 10;
end;

procedure terminate;
begin
write(ans);
close(input);close(output);
end;
begin
init;
doit;
terminate;
end.

第2个
program fact;
const
er:array[0..3] of longint=(6,2,4,8);
var
i,j,k,n:longint;
ans:longint;
begin
assign(input,'fact.in'); reset(input);
assign(output,'fact.out'); rewrite(output);

read(n); k:=0; ans:=1;

for i:=1 to n do
begin
j:=i;
while j mod 10=0 do
j:=j div 10;
while j mod 2=0 do
begin
inc(k);
j:=j div 2;
end;
while j mod 5=0 do
begin
dec(k);
j:=j div 5;
end;
ans:=(ans*j) mod 10;
end;
if k>0 then ans:=(ans*er[k mod 4]) mod 10;
writeln(ans);

close(output);
end.

第3个
program fact;
var
n,i,j,count,x,now:longint;
procedure reading;
begin
assign(input,'fact.in');reset(input);
assign(output,'fact.out');rewrite(output);
readln(n);
end;
procedure doit;
begin
count:=0;
x:=1;
for i:=1 to n do
begin
now:=i;
while now mod 2=0 do begin inc(count);now:=now div 2;end;
while now mod 5=0 do begin dec(count);now:=now div 5;end;
if (x*now mod 10=0)then x:=(x*now)div 10 else x:=(x*now)mod 10;
end;
end;
procedure after;
begin
if count>0 then
begin
if count mod 4=0 then x:=(x*6)mod 10;
if count mod 4=1 then x:=(x*2)mod 10;
if count mod 4=2 then x:=(x*4)mod 10;
if count mod 4=3 then x:=(x*8)mod 10;
end;
end;
begin
reading;
doit;
after;
writeln(x);
close(input);close(output);
end.

算法:首先 答案 一定是 2,4,6,8
基于这样一个事实:以上几个数 *6 末尾不变
那么,ans(k*10)=ans(k*6)=ans(k*16)
即: ans(k*2*5)=ans(k*2*8)
于是 将 n! 中 所有 的 因子 5 全部换成 8 结果是不变的
分类计算: 末尾为1,2,3,4,6,7,8,9 的 直接计算
5,0 把 一个 5 提取出来 ,全部换成8 直接计算得到
提取后 得到一个 子问题 : (N DIV 5)!的 末尾非零位
递归处理 即可

时间复杂度 O(LOG N)
温馨提示:内容为网友见解,仅供参考
第1个回答  2010-07-16
var
i,j,n:integer;
x,y:string;
function chengfa(a,b:string):string;
var
i,j,h:integer;
x:array[0..254] of integer;
c:string;
begin
fillchar(x,sizeof(x),0);
for i:=1 to length(a) do
begin
h:=ord(a[i])-48;
for j:=1 to length(b) do
x[i+j-1]:=x[i+j-1]+h*(ord(b[j])-48);
end;
c:='';
for i:=length(a)+length(b)-1 downto 1 do
begin
x[i-1]:=x[i-1]+x[i] div 10;
c:=chr(x[i] mod 10+48)+c;
end;
if x[0]>0 then
c:=chr(x[0] mod 10 +48)+c;
while true do
begin
if c[length(c)]='0' then
delete(c,length(c),1)
else
break;
end;
chengfa:=c;
end;
begin
readln(n);
x:='1';
for i:=1 to n do
begin
str(i,y);
x:=chengfa(x,y);
end;
writeln(x);
end.
第2个回答  2010-07-17
用高精,然后:
jishuqi:=0;
for i:=阶乘位数 downto 1 do
if 阶乘所得值最后一位是零, then inc(计数器) else write(计数器);
end.

求n的阶乘最后一位非0数字的问题。请人分析pascal代码
算法:首先 答案 一定是 2,4,6,8 基于这样一个事实:以上几个数 *6 末尾不变 那么,ans(k*10)=ans(k*6)=ans(k*16)即: ans(k*2*5)=ans(k*2*8)于是 将 n! 中 所有 的 因子 5 全部换成 8 结果是不变的 分类计算: 末尾为1,2,3,4,6,7,8,9 的...

阶乘末尾非零数求和 pascal
for i:=1 to n do begin p1:=p1*i; p:=p1;while p mod 10=0 do p:=p div 10;p:=p mod 10;s:=s+p;end;writeln(s);end.

阶乘最右边的非零位的值
人家要的是pascal程序。 规律:当n mod 10000000=0时,最右边的非零位的值是6。 极限数据(是49999999,不是50000000),貌似1s左右。 var n,i,s:longint; begin readln(n); s:=1; if n>10000000then begin s:=6; n:=n mod 10000000; end; for i:=2to n do begin if i mod 5<>...

C++编程小题,算阶乘最右边不是0的数
unsigned lastNonZeroDigitOfFactorial( unsigned n ) { unsigned exponentOfTwo = 0,exponentOfFive = 0,lastNonZeroDigit = 1;for ( unsigned i = 1; i <= n; i++ ) { unsigned temp = i;while ( temp % 2 == 0 ) { temp \/= 2;exponentOfTwo++;} while ( temp % 5 == 0...

pascal递归求助高手。。
我们知道:当N>0时,N!=N*(N-1)!,因此,求N!的问题化成了求N*(N-1)!的问题,而求(N-1)!的问题又与求N!的解法相同,只不过是求阶乘的对象的值减去了1,当N的值递减到0时,N!=1,从而结束以上过程,求得了N!的解。递归的调用:在Pascal程序中,子程序可以直接自己调用自己或间接调用...

pascal输入一个整数N(1<=N<=10000000),把它的各位数字倒序输出。N末 ...
问题的关键是处理末尾的0,程序如下:输入一个正整数,将其逆序输出,每个数字后有一个空格。输入一个正整数n,可以假设n在int范围内 输出将n按其逆序输出,每个数字后有一个空格,输出占一行。\/ include<stdio.h> int main(){int i;int n;scanf("%d",&n);int num = 0;for(i = 0; ; ...

Pascal求阶乘原理
在已经计算了i-1的的阶乘结果的时候,数值的最高有效数据位是A[m].在此基础上计算i的阶乘,需要从低A[1]到高位A[m]都乘以i,同时低位得数需要进位到高位,运算中,k作为保存进位用,当然,期间临时作为了数字乘以i的临时存放地点。a[j]*i+k; 该位j的结果是前次(i-1)阶乘的该位结果乘以...

怎样求一个数的阶乘(Pascal)
n!=n*(n+1)*(n+2)*...*3*2*1

pascal求10000以内n的阶乘?
目前几乎没有算法实现10000阶乘 201错误是数值溢出 integer的范围是-32767..32767,用作阶乘是远远不够的 简单递归只能算到12的阶乘:Program jiecheng ;var s,n:longint;function fac(n:integer):LONGINT;var k,t:integer;begin t:=1k:=2 to n do t:=t*k;fac:=t;end;begin writeln('...

从1*2*3*4一直乘到N,求末尾的0有几个,如何用PASCAL编
FACTORIAL_ZERO(n)1 cnt ← 0 2 while (n > 0)3 __do n ← n \/ 5 4 ___ cnt ← cnt + n 5 return cnt 其中除法是整数截尾除法。这个算法事实上就是数n的阶乘中因子5的个数。因为因子2比因子5少,所以因子5的个数就是因子10的个数,也就是末尾0的个数。自己体会一下吧。

相似回答