zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    [转]C# 中使用System.Net.Http.HttpClient 模拟登录博客园
    FastReport.NET 学习笔记--子分组添加事件无效的问题
    FastReport.NET 学习笔记--VS2010工具箱找不到fastreport的问题
    关于C#静态方法调用问题
    单链表——带头节点
    线性表——顺序存储结构
    重新出发
    ThreadPoolExecutor源码学习(1)-- 主要思路
    ThreadPoolExecutor源码学习(2)-- 在thrift中的应用
    [译]Cassandra的数据读写与压缩
  • 原文地址:https://www.cnblogs.com/dolphin0520/p/2014460.html
Copyright © 2011-2022 走看看