此题如果把阶乘计算出来,再求非零值,理论上可以,实际很难完成,阶乘值太大了,应该找到一些算法,以下一些规律,有助于解决问题:去掉所有因数末尾的0对结果无影响,如12300变为123。如果把末尾为5的因数去掉,那么结果只与所有因数的个位有关。所有偶数都可化为2的n次方乘一个奇数。把阶乘的所有因数分3种情况处理:末位非5的奇数,偶数,末位为5的数。
以下是实现的代码供参考。
#include<stdio.h>
#include <stdlib.h>
int main()
{
int notz( int );
int n;
scanf("%d",&n);
printf("%d\n",notz(n));
return 0;
}
int notz( int n)
{
int i,k,w;
unsigned int m,s;
k=1;
s=n;
w=s%10;
s/=10;
while(s!=0)
{
for(i=0 ;i<s;i++) k=(9*k)%10;
if(w>=3) k=(3*k)%10;
if(w>=7) k=(7*k)%10;
if(w>=9) k=(9*k)%10;
w=s%10;
s/=10;
}
if(w>=3) k=(3*k)%10;
if(w>=7) k=(7*k)%10;
if(w>=9) k=(9*k)%10;
//获得因子2的个数,处理偶数
m=0;
for(i=0 ;i<n-10;i+=10)
{
w=i+2;
while((w&1)==0){m++;w>>=1;}
k=(k*w)%10;
w=i+4;
while((w&1)==0){m++;w>>=1;}
k=(k*w)%10;
w=i+6;
while((w&1)==0){m++;w>>=1;}
k=(k*w)%10;
w=i+8;
while((w&1)==0){m++;w>>=1;}
k=(k*w)%10;
}
if(i+2<=n)
{
w=i+2;
while((w&1)==0){m++;w>>=1;}
k=(k*w)%10;
}
if(i+4<=n)
{
w=i+4;
while((w&1)==0){m++;w>>=1;}
k=(k*w)%10;
}
if(i+6<=n)
{
w=i+6;
while((w&1)==0){m++;w>>=1;}
k=(k*w)%10;
}
if(i+8<=n)
{
w=i+8;
while((w&1)==0){m++;w>>=1;}
k=(k*w)%10;
}
for(i=20;i<=n;i+=20)
{
s=i;
while(s%10==0)s/=10;
if((s&1)==0)
{
while((s&1)==0){m++;s>>=1;}
k=(k*s)%10;
}
}
//处理末尾为5的数
for(i=5;i<=n;i+=10)
{
s=i;
while(s%5==0)
{
s=s<<1;//用偶数2去乘,直到末尾非5
m--;
while(s%10==0)s/=10;
}
k=(k*s)%10;
}
for(i=50;i<=n;i+=50)
{
s=i;
while(s%10==0)s/=10;
if(s%5==0)
{
while(s%5==0)
{
s=s<<1;//用偶数2去乘,直到末尾非5
m--;
while(s%10==0)s/=10;
}
k=(k*s)%10;
}
}
//处理剩余偶数
for(i=m;i>0;i--) k=(k<<1)%10;
return k;
}
[
本帖最后由 jklqwe111 于 2015-7-30 18:42 编辑 ]