N!的从最末一个非0位开始自低位向高位数的第M位 soj 1115
2011-04-13 10:22
260 查看
阶乘
N的阶乘定义为:N!=N×(N-1)×……×2×1
请编写一个程序,输出N的阶乘的十进制表示中从最末一个非0位开始自低位向高位数的第M位。
其中:0<=N<=10000,1<=K<=5
例如:N=5,M=2,结果是1(5!=120) N=8,M=3,结果为0(8!=40320)
输入:
第一行一个整数M (1<=M<=100),代表测试数据的个数;
接下来M行,每行两个整数N,K
输出:
输出M行,每行一个整数,即测试数据的结果。
样例:
输入:
2
5 2
8 3
输出:
1
0
题意:很明了,就是求n!十进制表示中的从最末一个非0位开始自低位向高位数的第M位。有种思路就是将n!求出来,直接计算。
这种方法耗时828ms,memory 692K。
下面是另外一种思路
由于是求最末一个非0位开始自低位向高位数的第M位,那么末尾的0则可以忽略掉,并且最多只需保存5位结果即可(M<=5)。
如:n!=A1A2A3..........Ai000000000 Ai!=0
则只需取A(i+4)A(i+3)A(i+2)A(i+1)Ai这5位即可.
耗时0ms,memory 580K,明显效率高很多。
N的阶乘定义为:N!=N×(N-1)×……×2×1
请编写一个程序,输出N的阶乘的十进制表示中从最末一个非0位开始自低位向高位数的第M位。
其中:0<=N<=10000,1<=K<=5
例如:N=5,M=2,结果是1(5!=120) N=8,M=3,结果为0(8!=40320)
输入:
第一行一个整数M (1<=M<=100),代表测试数据的个数;
接下来M行,每行两个整数N,K
输出:
输出M行,每行一个整数,即测试数据的结果。
样例:
输入:
2
5 2
8 3
输出:
1
0
题意:很明了,就是求n!十进制表示中的从最末一个非0位开始自低位向高位数的第M位。有种思路就是将n!求出来,直接计算。
这种方法耗时828ms,memory 692K。
#include<iostream> #include<string.h> #include<stdio.h> #define MOD 10000 using namespace std; int main(void) { int t; scanf("%d",&t); while(t--) { int i,j; int n,k; int digit,carry; //digit表示当前计算的值的位数,carry表示进位 int f[10000]; char s1[50000]={'\0'}; char s2[5]; long long temp; f[0]=1; digit=1; scanf("%d%d",&n,&k); for(i=2;i<=n;i++) //求n! { carry=0; for(j=0;j<digit;j++) { temp=(long long)(f[j])*(long long)(i)+carry; //此处要用64位数据,防止数据溢出 f[j]=temp%MOD; carry=temp/MOD; } while(carry) { f[digit++]=carry%MOD; carry=carry/MOD; } } i=digit-1; while(f[i]==0) { i--; } sprintf(s2,"%d",f[i]); strcat(s1,s2); i--; for(;i>=0;i--) //将结果存进字符数组中以便于处理 { sprintf(s2,"%04d",f[i]); //不足4位前面补0 strcat(s1,s2); } for(i=strlen(s1)-1;i>=0;i--) { if(s1[i]!='0') break; } printf("%d\n",s1[i-k+1]-48); } return 0; }
下面是另外一种思路
由于是求最末一个非0位开始自低位向高位数的第M位,那么末尾的0则可以忽略掉,并且最多只需保存5位结果即可(M<=5)。
如:n!=A1A2A3..........Ai000000000 Ai!=0
则只需取A(i+4)A(i+3)A(i+2)A(i+1)Ai这5位即可.
耗时0ms,memory 580K,明显效率高很多。
#include<iostream> #define MOD 100000 using namespace std; int main(void) { int t; scanf("%d",&t); while(t--) { int n,k; int i,ans; ans=1; scanf("%d %d",&n,&k); for(i=n;i>=2;i--) { ans*=i; while(ans%10==0) //消除末尾的0 { ans/=10; } if(ans>=MOD) //只需保存末尾5位数字即可 ans%=MOD; } for(i=1;i<k;i++) { ans=ans/10; } ans=ans%10; printf("%d\n",ans); } return 0; }
相关文章推荐
- 输入一个十进制的正整数,从低位开始查找,找到第一个置位(1)比特的位置
- 开始DNN时出现的一个问题
- 开始学习JAVASCRIPT 学校要我参加一个项目 要用EXTJS 晕!!
- [5月21日的脚本] 在Windows 8开始按钮中创建一个切换用户磁贴 (VBScript)
- 返回一个字符串中重复出现的最长字串的长度及其开始字符
- 怎么开始写一个程序
- java中判断一个字符串是否包含另外一个字符串,如果包含,计算出字符串的开始位置
- 【微软100题】n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始, 每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。 当一个数字删除后,从被删除数
- 这算是一个小小的开始吧。。
- 《一个阶段的结束是另一个阶段的开始--记这两个月以来的前端实习生面试》
- 爱,由一个笑容开始,由一滴眼泪结束
- 怎样从0开始搭建一个测试框架_9——抽取器
- WPF Blend 一个动画结束后另一个动画开始执行(一个一个执行)
- 最近静不下来,要折腾,开始感觉时间又不够用了。其中一个就是想要把英语提升上去 幸好在我实施之前看到了这篇文章
- 用一个极简的Spring Demo开始记录2018年的满血转身
- 第一次写博客,想了很久要给自己留一个什么样的开始
- 怎样开始一个ASP网站的设计
- 如何开始使用PyCharm,并拥有一个高效的Python IDE
- 练习2-6 编写一个函数setbits(x, p ,n, y),该函数返回对x执行下列操作后的结果值: 将x中从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变。
- 开始写一个类似MSN的即时通讯软件,目的是边做边学习C#的通讯方面的类。