qduoj 114 阶乘问题

来源:互联网 发布:联城网络兼职是真是假 编辑:程序博客网 时间:2024/05/22 12:43

阶乘问题

发布时间: 2016年9月20日 12:11   最后更新: 2016年9月20日 15:33   时间限制: 1000ms   内存限制: 128M

小P遇到了一个题目,题目是让求n(0<=n<=10^18)的阶乘末尾0的个数,例如:3!=6末尾0的个数为0,5!=120末尾0的个数为1。

他写了以下的代码:

#include <stdio.h>int main(){int t;scanf("%d",&t);while(t--){long long n,i,num=1,ans=0;scanf("%lld",&n);for(i=1;i<=n;i++)num*=i;//num为n!while(1){if(num%10==0)//当末尾是0的话个数加一{num/=10;ans++;}else break;//末尾不是0的话退出循环}printf("%lld\n",ans);}return 0;}

可是提交没有通过,他通过考虑发现:首先,他的方法太慢n稍微大一点就要等好久,不满足题目的时间要求。其次,阶乘是很大的,虽然他用long long可是也最多算出20!,21!就超出的long long的范围。

他犯难了向你求助,聪明的你快写出正确的代码来帮助他吧!

第一行输入测试用例的个数T(0<t<=100)。对于每一个测试用例输入一行只有一个数n(0<=n<=10^18),代表让求n!末尾0的个数。

对于每一个测试用例在一行中输出一个数,代表n!末尾0的个数。

 复制
33520
01

4

思路:

对于这个题,我能想到的是: 因为题目中要求我们求末尾0的个数,那么我首先想到的就是 有一个10和其他数相乘末尾就会增加一个0,

我们就是要找里面能分出几个10;然后10又可以分为2和5,所以n!末尾0的个数取决于所能分出的2和5的个数中的最小值,我们又

知道能被2整除数的频率是肯定比5多的,也就是说我们只需要找所能分出的5的个数有多少就可以了

下面来讲一下核心代码:

我们知道一个数前面能被5整除的数的个数就是n/5;可是有很多数像25、75、100等它们贡献都不是一个5,那么怎么办呢?

我们只需要循环除5直到n==0为止,第一次表示能贡献一个5的(贡献多个5的也算在贡献一次里面),在循环。。

ans=n/5+n/5*5+n/5*5*5.....

#include<stdio.h>#include<string.h>int main(){    int t;   long long n;   scanf("%d",&t);   while(t--)   {   scanf("%lld",&n);       long long ans=0;       while(n)       { ans+=n/5;         n/=5;   }   printf("%lld\n",ans);   }   return 0;}

根据这个题我又在网上看到了好多类似的题目:

问题1:求N!最低位1的位置,从后往前数

思路:

对于这个题,其实和上一个题差不多;我们知道在二进制中乘以2相当于所有的数左移后面补0,/2就是右移前面补0;

我们要求最低位1的位置那么我们就需要找出来能够分出几个2来,然后最低位1的位置就是所有二的个数+1;

我来解释一下:

阶乘数中有一个2乘,那么就需要把数左移一位补0,有一个2就会贡献1个0,而我们知道每一个阶乘的最后一个数

都是1,所以最低位一开始都是从最后一位开始的;

//求N!的二进制表示中最低位1的位置;#include<stdio.h>int main(){   int n,sum;   while(scanf("%d",&n)!=EOF)   {    sum=0;      while(n)      { sum+=n/2;//sum>>=1;除2等同于右移一位;         n/=2;  }  printf("%d\n",sum+1);     }   return 0; } 

问题2:

判断一个数是否为2的n次方

思路:相信这个题对于大家来说都不是难题吧,也比较好想;

我们只需要看 m&(m-1)==0?==0就是 !=0则不是

#include<stdio.h>int n; int main(){    while(scanf("%d",&n)!=EOF)     {     n=n&(n-1);          if(n==0)           printf("YES\n");           else           printf("NO\n"); } return 0; } 

1 0