N!的从最末一个非0位开始自低位向高位数的第M位 soj 1115

简介:

       阶乘

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 ;
}
复制代码

相关文章
|
2月前
二进制数从0开始的前几个数
二进制数从0开始的前几个数:
386 0
|
4月前
|
机器学习/深度学习 网络协议 Windows
几个数相加
几个数相加。
75 4
单字节,双字节,四字节能够表示的数值大小范围分别是多少
单字节,双字节,四字节能够表示的数值大小范围分别是多少
|
C语言
C语言之将长整型数中每一位上为奇数的数依次取出,构成一个新数放在t中。高位仍在高位,低位仍在低位。
C语言之将长整型数中每一位上为奇数的数依次取出,构成一个新数放在t中。高位仍在高位,低位仍在低位。
269 0
遇7避过(输出1~100内的安全数,安全数不能带有7,不能被7整除
遇7避过(输出1~100内的安全数,安全数不能带有7,不能被7整除
76 0
|
算法
求二进制位中一的个数
求二进制位中一的个数
87 0
|
IDE 开发工具
什么是进制中的低位、高位
什么是进制中的低位、高位
打印0~100000之间的水仙花数, 水仙花数指一个n位数,其各位数的n次方之和正好等于该数本身
打印0~100000之间的水仙花数, 水仙花数指一个n位数,其各位数的n次方之和正好等于该数本身
121 0