luoguP1134 【阶乘问题】

P1134 阶乘问题

传送门

题目描述

也许你早就知道阶乘的含义,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

输出格式:

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

输入输出样例

输入样例#1:

12

输出样例#1:

6

说明

U S A C O T r a i n i n g S e c t i o n 3.2

小菜鸡好久没有和大家见面了,今天感到格外开心。

来,帮小菜鸡再挑战新高度。

上个星期,和一帮师兄(都是大神)听课。

其中有一道题比较感兴趣。

那就是本题了。

难度为 普及/提高- 。

小菜鸡一开始没开题觉得很难,毕竟是和一群 d a l a o 上课。

但一看题其实并没有想象的那么难,开来审题还是非常重要的。

这道题小菜鸡觉得和下面这道小学生赛题目,有点相似。

1.连续零(难度系数:容易)
(1.pas/cpp/c)

【题目描述】
输入两个正整数a和b,s为a到b之间(包含a、b)所有整数的乘积,求s末尾从个位开始有多少个连续的0。
比如a=1,b=7,那么s=1*2*3*4*5*6*7=5040,答案就是1,不是2。

【输入格式】
一行两个正整数,分别表示a和b(1<=a,b<=10^6)。

【输出格式】
输出一行一个整数,即0的个数。

【输入输出样例1】
lxl.in  lxl.out
1 10    2

【输入输出样例2】
lxl.in  lxl.out
4 25    6

【数据范围】
1<=a,b<=1000 000

那我们先从这道题入手。

首先审题,非常重要。

主要讲的是: a b 的乘积,末尾有几个 0

那末尾 0 怎么产生的呢?

2 × 5 = 10

也就是说,找 2 5 的个数,然后比较谁少,就是答案。

忘了告诉大家这道题有个坑, a 不一定比 b 小,交换一下就可以了。

参考程序:

#include<cstdio>//调用      scanf      库
long long a,b,t,x,y,s1=0,s2=0;//竞赛最好开      long long      ,避免数据太大的情况
int main()//主函数
{
    scanf("%lld %lld",&a,&b);//输入
    //注意      longlong      地址符是      %lld
    if(a>b)t=a,a=b,b=t;//坑的处理
    for(long long i=a;i<=b;i++)
    {
        x=i,y=i;
        while(x%2==0)x/=2,s1++;
        while(y%5==0)y/=5,s2++;
    }
    //算出2和5的个数
    if(s1<s2)printf("%lld",s1);
    else printf("%lld",s2);
    //输出小的
    return 0;
}

回归正题,题目类似

不过洛谷上是 n ! ,就没有刚刚的坑点了。

其实,刚刚有个优化,直接判断 10

因为, 2 5 才得到 10 ,那个少一个都不行,所以自然得出少的个数。

来,一起大代码:

#include<cstdio>//调用      scanf      库
#define ll long long//long long      可开可不开,不过小菜鸡喜欢
ll n,ans=1;//ans      做累乘
int main()//美好的开始
{
    scanf("%lld",&n);//完美输入
    for(ll i=1;i<=n;i++)//开始n的阶乘
    {
        ans*=i;//累乘
        while(ans%10==0)ans/=10;//能被10整出就除
        ans%=10000000;//记得%10000000,错了可不要怪小菜鸡哦
    }
    printf("%lld",ans%10);//注意最后要%10,想了大约半个小时
    return 0;//下次再见
}

猜你喜欢

转载自blog.csdn.net/qq_41857193/article/details/79944295
今日推荐