ACM北大的第1001題

算法一直被認爲是高手纔可以接觸的東西,雖說大學裏老師都說程序=數據結構+算法,可是在實際工作中用到算法的機會真的不多。最近突然覺得,如果要做高級的工作,比如架構師,搜索,自然語言處理,數據挖掘等等方面,算法是一個非常重要的東西,因此覺得開始練習算法,提高自己的算法能力。說到算法的話,ACM肯定是一個必知的詞彙了,總覺得做ACM的人很牛,我也想成爲一個牛人,雖然水平很爛。

果然,北大的第一道題目就把我難住了(A+B那題除外,那基本就是例子),題目是這樣的:

Description
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 <= 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 R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.

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

我花了時間自己從頭到尾實現了整個算法:

package com.seiya;

import java.util.ArrayList;
import java.util.Scanner;

/**
 * Created by dell on 2015/10/27.
 */
public class Exponentiation {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        while(scanner.hasNext()) {
            String str = scanner.nextLine();
            if(str.equals("EOF")) break;
            //System.out.println(str);
            //long time1 = System.currentTimeMillis();
            String real = str.substring(0,str.indexOf(" ")).trim();
            //System.out.println(str);
            String n = str.substring(str.lastIndexOf(" ")).trim();
            //System.out.println("real: "+real+", n: "+n);
            String result = real;
            int nn = Integer.valueOf(n);
            if(!real.contains(".")) {
                for (int i = 1; i < nn; i++) {
                    result = multiply(result, real);
                }
            }else {
                int point = (real.length()-1)-real.indexOf('.');
                //System.out.println("point:"+point);
                real = real.replace(".","");
                //System.out.println("real:"+real);
                int rp = point*nn;
                result = real;
                for (int i = 1; i < nn; i++) {
                    result = multiply(result, real);
                }
                String r1 = result.substring(0,result.length()-rp);
                String r2 = result.substring(result.length()-rp);
                result = r1+"."+r2;
                // 去除末尾的0
                for(int i = result.length()-1;i >= 0; i--) {
                    if(result.endsWith("0")) {
                        result = result.substring(0,result.length()-1);
                    }
                }
                // 去除小數點前的0
                String prefix = result.substring(0,result.indexOf("."));
                if(prefix.equals("0")) {
                    result = result.substring(1);
                }
            }
            System.out.println(result);
            //long time2 = System.currentTimeMillis();
            //System.out.println("time: "+(time2-time1));
        }

    }

    public static String multiply(String a,String b) {
        String rstr = "";
        ArrayList<ArrayList<Integer>> tempResult = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> result = new ArrayList<Integer>();
        char[] array1 = a.toCharArray();
        char[] array2 = b.toCharArray();
        for(int i = array1.length-1; i >= 0; i--) {
            ArrayList<Integer> temp = new ArrayList<Integer>();
            for(int j = array2.length-1; j >= 0; j--) {
                int ai = Integer.parseInt(""+array1[i]);
                int bj = Integer.parseInt(""+array2[j]);

                temp.add(ai*bj);
            }
            for(int k=0;k<temp.size()-1;k++) {
                int c = temp.get(k);
                if(c>=10) {
                    int d = temp.get(k+1);
                    d += c/10;
                    temp.set(k+1,d);
                    c=c%10;
                    temp.set(k,c);
                }
            }
            tempResult.add(temp);
        }

        result = tempResult.get(0);
        for(int i = 0; i < tempResult.size()-1; i++) {
            result = myadd2(result, tempResult.get(i + 1), i + 1);
        }

        for(int i = result.size()-1; i >= 0; i--) {
            rstr += result.get(i);
        }
        return rstr;
    }

    public static ArrayList<Integer> myadd2(ArrayList<Integer> a,ArrayList<Integer> b,int k) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        for(int i = 0;i < k;i++) {
            result.add(a.get(i));
        }

        for(int i = k; i < a.size(); i++) {
            int temp = a.get(i)+b.get(i-k);
            if(temp>=10) {
                result.add(temp % 10);
                b.set(i-k+1,b.get(i-k+1)+temp/10);
            }else {
                result.add(temp);
            }
        }
        result.add(b.get(b.size()-1));
        return result;
    }
}

總體上思路是這樣的:先實現一個大數相乘的乘法運算,然後把冪運算看做是很多個大數相乘,根據小數點的位數,再決定該把小數點放在哪裏,然後去除多餘的0。在實現大整數乘法的運算時,先實現各個數字相乘,並把結果暫存在一個ArrayList中,然後取出結果並錯位相加,就得到乘法的結果。

感覺上應該是沒有問題的,事實上我經過測試結果都是正確無誤的,不過在北大的ACM算法提交的時候就報錯了,話說我也不知道爲什麼錯了,錯在哪裏,等我以後水平更高再來看吧。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章