题解系列003 | 洛谷CF869B 【The Eternal Immortality】

原题传送门:The Eternal Immortality

读完题目,我们可以发现这题实质上就是让我们求两个数的阶乘的商模 10 10 10的余数。但题目中给的数据是 0 ≤ a ≤ b ≤ 1 0 18 0\leq a\leq b\leq 10^{18} 0ab1018,显然直接使用阶乘会直接炸掉(用 python 也会 TLE),因此这种方法直接否决。

但是,经过一番观察,我们发现这里 a ! a! a! b ! ( a ≤ b ) b!(a\leq b) b!(ab)有很大一部分是“重叠”的,即:

b ! a ! = b ⋅ ( b − 1 ) ⋅ … ⋅ 1 a ⋅ ( a − 1 ) ⋅ … ⋅ 1 = b ⋅ ( b − 1 ) ⋅ … ⋅ ( a + 1 ) \dfrac{b!}{a!}=\dfrac{b\cdot (b-1)\cdot\ldots\cdot1}{a\cdot(a-1)\cdot\ldots\cdot1}=b\cdot(b-1)\cdot\ldots\cdot(a+1) a!b!=a(a1)1b(b1)1=b(b1)(a+1)

因此可以利用这个方法大大减缓计算量。

但这样还是不行的。注意在这种情况下,我们并没有对差距特别大的数做出实际的优化。比如说我们输入 1 1 1 100000000000 100000000000 100000000000,用上面的公式还是需要将 100000000000 100000000000 100000000000个数相乘,没有减少计算量。因此还需要发掘其它的性质。

  • 这里我们注意到模 10 10 10计算的优点:碰到一个 5 5 5和一个 2 2 2个位基本就是 0 0 0了。

  • 进一步看,也即当两个数满足 b − a > 5 b-a>5 ba>5时, b ! a ! \dfrac{b!}{a!} a!b!的末位一定是 0 0 0(这里用到了“任何连续 n n n个数的乘积一定被 n n n整除”这个性质)

  • 这样计算就大大优化了。比如说我们输入 1 1 1 100000000000 100000000000 100000000000,根据上面的算法,无需计算就可以直接得出答案是 0 0 0。因此可以看到,用适当的数学知识可以减轻计算机的工作量!

上代码:

#include <iostream>
using namespace std;

int main()
{
	long long a, b, al, bl;
	int ans = 1;
	cin >> a >> b;
	if (b - a > 5)
		cout << 0;
	else
	{
		for (long long i = a + 1; i <= b; i++)
		{
			ans = (ans % 10) * (i % 10);
		}
		cout << ans % 10;
	}

	return 0;
}

(留个赞再走吧

欢迎大家关注我的博客!
我的洛谷账号:这是我
我的洛谷团队:这是我的团队
欢迎大家关注我,并加入我的团队哦^ _ ^
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值