PKU 1055 The Last Non-zero Digit

来源:互联网 发布:停车场计费规则 java 编辑:程序博客网 时间:2024/04/30 18:19

          The Last Non-zero Digit

 

题目大意:

给N,M( N (0 <= N<= 20000000), M (0 <= M <= N)),求 NPM最后一位不是零的数。,即求n!/(n-m)! 最后一位不是0 的数字。

解题分析:

N (0 <= N<= 20000000), M (0 <= M <= N),N,M的范围都很大,直接求出来的可能是不现实的。所以要找一个比较好的算法解决这个问题。

1.先把范围缩小。怎样求出n!的最后一个不是0的数呢?

先举个简单的例子,分析一下规律。

比如说要求10!的最后一个不是0的数。10!=1*2*3*4*5*6*7*8*9*10。.由于质数为2和5的数相乘后尾数会为0,所以我们可以除去质因数2和5数。

1*2*3*4*5*6*7*8*9*10,去掉质因数为2和5的结果为:1*1*3*1*1*3*7*1*9*1,去除了质因数剩下的数字就只用1、3、7、9了。不为零的尾数就应该是这些数字相乘取它们的个位数,还要加上2、5的影响。因为2*5=10,成对的2、5不影响最后一个不是0 的尾数。那就得看剩余几个2或5,又由于2的个数一定比5多,所以最后只要考虑剩余的2对尾数的影响。

综上:最后一个不是0的尾数就是:1、3、7、9相乘的结果在乘以 (与5成对后剩余的2的个数)

总结一下,求10!最后一个非0位的步骤如下:
step1
:首先将10!中所有2,5因子去掉;
step2
:然后求出剩下的一串数字相乘后末尾的那个数。
step3
:由于去掉的2比5多,最后还要考虑多余的那部分2对结果的影响。
step4
:得出结果。

      那么现在的问题就是怎样求出尾数2、5和3,7,9的个数了。

求分解为质数后2的个数

 int get2(int n)

{

  if(n==0) return 0;

  return n/2+get2(n/2);

}

求尾数5的个数

int get5(int n)

{

  if(n==0) return 0;

  return n/5+get5(n/5);

}

那是不是3,7,9也是这样求呢?再来分析一下:

以1*2*3*4*5*6*7*8*9*10为例,根据奇偶性可以分成偶数列和奇数列

即分成:1,3,5,7,9   2,4,6,8,10

可以发现,实际上2,4,6,8,10中的个数也就是1 2 3 4 5中的个数.

f(n) = f(n/2) + g(n),g(n)表示奇数列中的数目,所以我们需要解决g(n) .

而奇数:1 3 5 7 9 11 13 15 17。。。又可以分为尾数为1 3 7 9的数和尾数为5的数。

所以g(n,x)=n/10+(n%10>=x)+g(n/5,x)

 

在求3,7 ,9的各自相乘尾数是还有一个技巧那就是 它们的尾数都是循环的。

如3, =1   =3  =9  =27  =81 。。。尾数为:(1 3 9 7) 的循环。