题解 P2529【[SHOI2001]击鼓传花】

P2529 [SHOI2001]击鼓传花

提供一种不一样的思路。

题意

f(n)=n! 中最后一位非 0 数,1n10100

思路

显然不能暴力。

引入符号 s(n)=1×2×3×4×6×...×9×11n! 中不包含因数 5 的项的乘积。

a(n) 表示 s(n) 中最后一位,显然,a(n)0

对于 n=1,2,3,...,我们发现 a(n)=1,2,6,4,4,4,8,4,6,6,6,2,6,4,4,4,8,4,6,6,6,...,发现没有?循环节 2,6,4,4,4,8,4,6,6,6

我们可以先处理出 n10f(n),然后讨论一下。

n!=s(n)×5n5×(n5)!=s(n)2n5×10n5×(n5)!f(n)=s(n)2n5×(n5)! 的最后一位非 0 数。

又十分显然 f(n)=s(n)2n5×f(n5) 的最后一位非 0 数。

考虑 a(n)a(n2) 的关系。

经过找规律,a(n)=2a(n2)=6a(n)=6a(n2)=8a(n)=8a(n2)=4a(n)=4a(n2)=2 循环。

a(n) 循环,容易计算,所以 s(n)2n5 的最后一位容易计算。

所以 f(n) 就能计算了。

因为要高精度,于是我用了 Python 实现。

Code:

a=[6,2,6,4,4,4,8,4,6,6]
sm=[1,2,6,4,2,2,4,2,8,8]
t=[2,6,8,4]
def geta(n):
    if n==1:
        return 1
    else:
        return a[(n-1)%10]
def gets(n):
    last=geta(n)
    id=t.index(last)
    return t[(id+(n//5))%4]
def f(n):
    if n<=10:
        return sm[n-1]
    else:
        return (gets(n)*f(n//5))%10
def testt(n):
    s=1
    for i in range(2,n+1):
        s=s*i
    return s
fl=True
while fl:
    try:
        n=int(input())
        print(f(n))
    except:
        fl=False

再见,qwq~

posted @   ffffyc  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示