Description
给定一个N*M的矩阵,记录左上角为(1,1),右下角为(N,M),现在从(1,1)开始取数,每次只能向下或向右移动一个单位,最终到达(N,M),我们把路径上所有的数相乘,记为C。使C的结果最大已经不能满足我们了,现在我们想让C末尾的零最少。
Ps.11000末尾有3个零,100000100末尾有2个零。
Input
输入文件matrix.in的第一行包含两个正整数N,M表示矩阵大小。
接下来N行每行M个正整数给出整个矩阵。
Output
输出文件名为matrix.out。包含一个整数表示所求最小值。
分析
首先,如果两个数的积的末尾n个零,那这两个数的质因数里肯定有n对2和5。(多个数也是一样的)
那么,我们就要使路径上的数所包含的2或5最少。
先预处理出每个数分别包含的2和5的个数,把2的个数放在一个图里(按原来的顺序)(5也一样)
然后分别在两幅图找一条个数最小的路径,把两个结果比较,较小的那个就是结果。
ps:找路径我一开始写成广搜,后来发现可以用类dp的方式
f[i,j]=min(f[i−1,j]+a[i,j],f[i,j−1]+a[i,j])
const
dx:array[1..2] of longint=(0,1);
dy:array[1..2] of longint=(1,0);
var
i,j,k,z:longint;
n,m:longint;
a,b,f:array[0..2000,0..2000] of longint;
ans:longint;
function max(x,y:longint):longint;
begin
if x>y
then exit(y)
else exit(x);
end;
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(k);
z:=k;
while (z<>0) and (z mod 2=0) do
begin
a[i,j]:=a[i,j]+1;
z:=z div 2;
end;
while (z<>0) and (z mod 5=0) do
begin
b[i,j]:=b[i,j]+1;
z:=z div 5;
end;
end;
readln;
end;
fillchar(f,sizeof(f),$7f);
f[0,1]:=0;
for i:=1 to n do
for j:=1 to n do
f[i,j]:=max(f[i-1,j]+a[i,j],f[i,j-1]+a[i,j]);
ans:=f[n,m];
fillchar(f,sizeof(f),$7f);
f[0,1]:=0;
for i:=1 to n do
for j:=1 to n do
f[i,j]:=max(f[i-1,j]+b[i,j],f[i,j-1]+b[i,j]);
if ans<f[n,m]
then write(ans)
else write(f[n,m]);
end.