求n得阶乘得最后一位非零数字
如题,最后一位数好求,他只和最后一位相乘后的最后一位有关,唯一影响我们得是末尾0,而阶乘中末尾0来自于2和5,(10得话可以看成2 * 5),所以有这个思想我们可以筛选出1 * 2 * 3 * .... * n中包含2和5得个数
如下:
1 2 3 4 5 6 7 8 9 10 | int get2( int n) { if (n == 0) return 0; return n / 2 + get2(n / 2); } int get5( int n) { if (n == 0) return 0; return n / 5 + get5(n / 5); } |
解释:
对于1 2 3 4 5 6 7 8 9 ^ 25 26 27 28 29 30
我要想找里面任何一个包含5得数字,一眼看去筛选出含有5得只有:5 10 15 20 25 30,但是有的含有两个5啊,那我就提出一个5,把他降一个形态,然后继续去寻找……
30 /5 = 6 得到原型 6!,其余得均为无关数,不必去管
继续筛选1 2 3 4 5 6,这个6得阶乘,是上面筛选完后产生得,可能还存在着得数,这些数将会递归进行二次筛选
这样我们完成了第一步,筛选完后,你会发现原来的阶乘
1 2 3 4 5 6 7 8 9 ^ 25 26 27 28 29 30
变成了
1 1 3 1 1 3 7 1 9 1 11 3 13 7 3
这样看反而有所不大直观,但是能够得出得就是最后剩下得就是1 3 7 9(尾数),1没有作用,而 3 7 9 结果观察,他们自身得n次方得位数有个周期
1 3 9 7
1 7 9 3
1 9 1 9
所以我们就可以取寻找原来那些数含有3,5,7得个数
还是先看看原型
1 2 3 4 5 6 7 8 9 ^ 25 26 27 28 29 30
step 1对于这些数,我们要做得是奇偶分开
1 3 5 7 9 。。。 2 4 6 8 10.。。。
对于偶数唯一要做得就是抽2变型(递归step1)
step2 对于奇数我们可以求取了,奇数中,每10个数中肯定含有1个3,7,9,所以返回得值中有n / 10然后对于非整得数,还要考虑其最后一位得大小选择性得+1 即+(n % 10 >= x)
然后奇数中还有5,这个根据我们得拆分,是不应该纯在得所以递归 step 2(n/ 5 --- 抽5降形)
为什么重复step2而不是step1呢?抽了5后不会出现偶数得情况吗??
因为 奇偶分家得时候,进来的奇数已经不再是一个完整得阶乘了,但是对3 7 9 得寻找毫无影响,因为偶数都一眼找不出来,所以进来得5 是 5 15 25,降型后也是 1 3 5 .。。直接去应用step2
到此就能够实现了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | int g( int n, int x) { if (n == 0) return 0; return n / 10 + (n % 10 >= x) + g(n / 5,x); //这里的5分解后只有奇数没有偶数ggm1,3,5,7....,然后再在奇数里筛选 //因为10,20,这样的一开始再getx中是筛不进来得!! } int getx( int n, int x) //寻找这个数中 { if (n == 0) return 0; return getx(n / 2,x) + g(n,x); } int numtable[4][4] ={ 6,2,4,8, 1,3,9,7, //注意顺序得安排取0得时候代表有4个得时候得余数 1,7,9,3, 1,9,1,9 }; int main() { int n,m; while (~ scanf ( "%d%d" ,&n,&m)) { int num2 = get2(n) - get2(n-m); int num5 = get5(n) - get5(n-m); int num3 = getx(n,3) - getx(n-m,3); int num7 = getx(n,7) - getx(n-m,7); int num9 = getx(n,9) - getx(n-m,9); int res = 1; if (num5 > num2) { res = 5; } else if (num5 < num2) //WRONG 2 :只有不相等得时候才能乘法,因为numtable[0][0]也是有数据得肯定会造成影响 { res *= numtable[0][(num2 - num5)%4]; //WRONG 1 :乘上得是多余得2!!! res %= 10; } if (res != 5) { res *= numtable[1][num3%4]; res %= 10; res *= numtable[2][num7%4]; res %= 10; res *= numtable[3][num9%4]; res %= 10; } printf ( "%d\n" ,res); } return 0; } |
__EOF__

本文链接:https://www.cnblogs.com/DF-yimeng/p/8672333.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律