zoukankan      html  css  js  c++  java
  • Uva 748 Exponentiation(大数相乘)

    Exponentiation 

    Time limit: 3.000 seconds

    Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems.

    This problem requires that you write a program to compute the exact value of Rn where R is a real number (0.0 < R < 99.999) and n is an integer such that $0 < n \le 25$.

    Input 

    The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

    Output 

    The output will consist of one line for each line of input giving the exact value of Rn. Leading zeros and insignificant trailing zeros should be suppressed in the output.

    Sample Input 

    95.123 12
    0.4321 20
    5.1234 15
    6.7592  9
    98.999 10
    1.0100 12
    

    Sample Output 

    548815620517731830194541.899025343415715973535967221869852721
    .00000005148554641076956121994511276767154838481760200726351203835429763013462401
    43992025569.928573701266488041146654993318703707511666295476720493953024
    29448126.764121021618164430206909037173276672
    90429072743629540498.107596019456651774561044010001
    1.126825030131969720661201
    

    Miguel A. Revilla 
    2000-02-09
     
    测试数据:
     
    input:
     

    0.0110 1
    1000. 2
    1000 4
    10 1
    10.0 1
    10. 1

    output:

    .011
    1000000
    1000000000000
    10
    10
    1

    #include<stdio.h>
    #include<string.h>
    #include<time.h>
    #define MAXN 1000
    int temp[MAXN];
    int temple[MAXN];
    int patience[MAXN];
    int sum[MAXN], large = 0;
    char last[MAXN];
    
    int add(int len, int level)
    {// 一次相乘时累加各各位数上相乘得到的数 
        int i, j, e, item;
        for(i=0,e=0; i<len; ++i)
        {
            item = (e + temple[i] + sum[i+level]);
            sum[i+level] = item%10;
            e = item/10;
        }
        for(; e!=0; ++i)
        {
            item = e + sum[level+i];
            sum[i+level] = item%10;
            e = item/10;
        }
        if(i+level > large) large = i+level;
        
    }
    
    int multi(int n, int len)
    {// 进入这个函数时先将patience的值赋予底的值 
        int i, j, e, cnt, strlen, item, t, m, t_n = n-1; // t_n的值为指数减1,统计需要相乘的次数 
        memset(sum, 0, sizeof(sum));
        memset(temple, 0, sizeof(temple));
        large = len;
        while(t_n--)
        {
            strlen = large;
            for(i=0; i<len; ++i)  
            {// 一次for循环完成时,两个大数相乘的目的达到 
                item = temp[i];
                for(j=0, e=0; j<strlen; ++j)
                {
                    m = item*patience[j];
                    temple[j] = (e + m)%10;
                    e = (e + m)/10;
                }
                cnt = strlen;
                if(e) temple[j] = e, cnt++;
                add(cnt, i);
                memset(temple, 0, sizeof(temple)); 
            }
            
            memset(patience, 0, sizeof(patience));
            for(i=0; i<large; ++i) patience[i] = sum[i];
            memset(sum, 0, sizeof(sum));   // 每次将相乘得到的结果赋值给patience时将sum归零
        }    
        
        return 0;
    }
    
    int main()
    {
        clock_t begin, end;
        int i, j, k, cnt, t, len, m, high, low;
        char input[10], *str;
        int n;
        begin = clock();
         while(scanf("%s%d", input, &k) != EOF)
         {
             len = strlen(input);
             m = -1;
             if((str = strchr(input, '.')) != NULL)
             m = len - 1 - (str - input);   // m 的作用是计算小数点后面有几位小数,无小数点时m=-1 
            memset(temp, 0, sizeof(temp));
            memset(patience, 0, sizeof(patience));
            for(i=len-1,n=0; i>=0; --i)
             if(input[i] != '.') temp[n++] = patience[n] = input[i] - '0';
             
             if(m != -1) len--; 
            if(k>=2) multi(k, len);    
            else if(k == 1)  // 处理指数为1的情况 
            {
                high = len-1, low = 0;  
                // high 和 low 两个变量主要是消除前缀零和尾数零的情况, 同时,若存在小数点 
                // 而且是有必要消除时,比如说1000. 用这两个变量根据情况判断也可以消去 
                for(i=0; input[i] == '0'; ++i); low = i;
                if(m != -1)
                {
                    for(i=len-1; input[i] == '0'; --i); high = i;
                    if(input[high] == '.') high--;
                } 
                
                for(i=low; i<=high; ++i) printf("%c", input[i]);
                printf("\n");
                continue;
            }
            
            
            
            if(m == -1) // 处理无小数点的情况,而这时的尾数零不用消去 
            {
                low = 0, high = large - 1;
                for(i=large-1; patience[i] == 0; --i); high = i;
                for(i=high; i>=low; --i) printf("%d", patience[i]);
                printf("\n");
            }
            else
            {// 当存在小数点时,必须先将小数点放入大数内才能开始消去前缀零和尾数零 
                cnt = 0;
                t = m*k;  // 计算最后一共有几个小数,没有先处理尾数零的其中原因之一就是避免不能准确计算t 
                memset(last, 0, sizeof(last)); // 建立一个字符串数组,作用是存储加入小数点后的大数 
                for(i=0; i<t; ++i)
                {
                    sprintf(last+cnt, "%d", patience[i]);  // sprintf函数将整型转换成了字符放入了字符串中 
                    cnt++;
                }
                last[cnt++] = '.';   // 放入小数点 
                for(; i<large; ++i)
                {
                    sprintf(last+cnt, "%d", patience[i]); 
                    cnt++;
                }
                last[cnt] = '\0';
                len = strlen(last);
                low = 0, high = len-1;
                for(i=len-1; last[i] == '0'; i--); high = i;  // 同样的形式处理前缀零和尾数零 
                for(i=0; last[i] == '0'; i++); low = i;
                if(last[low] == '.') low++; 
                for(i=high; i>=low; i--) printf("%c", last[i]);
                printf("\n");
            }
            
         }
        end = clock();
        printf("time = %dms\n", end - begin);
        return 0;
    }

    解题思路:

    先将浮点数转换成整型,同时统计小数点后面数得个数,再进行大数相乘   1y

  • 相关阅读:
    titlebar和actionbar上的按钮设置
    Android 实现闹钟功能
    关于禁止ViewPager预加载问题【转】
    RabbitMQ基础概念详细介绍
    Android 使用Android Studio + Gradle 或 命令行 进行apk签名打包
    Android4.0的Alertdialog对话框,设置点击其他位置不消失
    android MediaCodec 音频编解码的实现——转码
    一个android的各种控件库
    golang的验证码相关的库
    android studio提示unable to run mksdcard sdk
  • 原文地址:https://www.cnblogs.com/liaoguifa/p/2832936.html
Copyright © 2011-2022 走看看