题目很简单
求 n! 从右向左最大非零位
如果模拟这道题貌似是可以过得,但是假设数据量如果够大,这种模拟方法还是不够好,所以我们需要进行一些智慧的改进。
既然最大非零位,那右边的 0 必定需要被消掉,那么 0 就是来自于 10 这个因子的,而 10 很明显可以拆解成 2*5,那么我们先筛选一遍,因子,抛去所有的含 2 5 10 的因子(当然如果2或5其中一个比另一个多 我们还要乘上多出来的部分)
至于剩下部分就暴力对10取模就好了。。
看了下思路和题解很像,但是感觉他们还有一种方法就是找出了规律。。我没有细看感觉可能更加优秀一些。。但是如果按照这种方法效率 O(n)的话 貌似还可以接受,如果数字更大。。估计需要找规律了。。。
以下是 AC 代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
ll c1,c2;
ll n;
int main()
{
scanf("%lld",&n);
ll ans = 1;
for(ll i=1;i<=n;i++)
{
ll t = i;
while(t % 10 == 0)
t/=10;
while(t % 2 == 0)
{
t /= 2;
c1 ++;
}
while(t % 5 == 0)
{
t /= 5;
c2 ++;
}
ans *= t;
ans %= 10;
}
if(c1 > c2)
{
for(int i=1;i<=c1-c2;i++)
{
ans *= 2;
ans %= 10;
}
}
if(c2 > c1)
{
for(int i=1;i<=c2-c1;i++)
{
ans *= 5;
ans %= 10;
}
}
printf("%lld\n",ans);
return 0;
}