HDOJ 4814 Golden Radio Base【推公式 + 暴力】

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4814

题意:就是求10进制数的(1+√5)/2进制表达式

分析:根据题意,的公式可以推出φ的任意阶的表达式:a + b * φ,然后就是暴力算,开始用c++搞,然后WA了,看了题解发现是精度不够,于是换Java写,搞了个高精度开方,根据枚举大概精度到20位就好,表达式的误差1e-10就可以了。。这题具体就是乱搞

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Scanner;


public class Main {
    
    static long f[] = new long[100];
    static int cnt;
    static long a, b;
    static long lim = 1000000000;
    
    final static BigInteger HUNDRED = BigInteger.valueOf(100);
    
    public static BigDecimal sqrt(BigDecimal number, int scale, int roundingMode) {
        if (number.compareTo(BigDecimal.ZERO) < 0)
            throw new ArithmeticException("sqrt with negative");
        BigInteger integer = number.toBigInteger();
        StringBuffer sb = new StringBuffer();
        String strInt = integer.toString();
        int lenInt = strInt.length();
        if (lenInt % 2 != 0) {
            strInt = '0' + strInt;
            lenInt++;
        }
        BigInteger res = BigInteger.ZERO;
        BigInteger rem = BigInteger.ZERO;
        for (int i = 0; i < lenInt / 2; i++) {
            res = res.multiply(BigInteger.TEN);
            rem = rem.multiply(HUNDRED);
            
            BigInteger temp = new BigInteger(strInt.substring(i * 2, i * 2 + 2));
            rem = rem.add(temp);
            
            BigInteger j = BigInteger.TEN;
            while (j.compareTo(BigInteger.ZERO) > 0) {
                j = j.subtract(BigInteger.ONE);
                if (((res.add(j)).multiply(j)).compareTo(rem) <= 0) {
                    break;
                }
            }
            
            res = res.add(j);
            rem = rem.subtract(res.multiply(j));
            res = res.add(j);
            sb.append(j);
        }
        sb.append('.');
        BigDecimal fraction = number.subtract(number.setScale(0, BigDecimal.ROUND_DOWN));
        int fracLen = (fraction.scale() + 1) / 2;
        fraction = fraction.movePointRight(fracLen * 2);
        String strFrac = fraction.toPlainString();
        for (int i = 0; i <= scale; i++) {            
            res = res.multiply(BigInteger.TEN);
            rem = rem.multiply(HUNDRED);
            
            if (i < fracLen) {
                BigInteger temp = new BigInteger(strFrac.substring(i * 2, i * 2 + 2));
                rem = rem.add(temp);
            }
            
            BigInteger j = BigInteger.TEN;
            while (j.compareTo(BigInteger.ZERO) > 0) {
                j = j.subtract(BigInteger.ONE);
                if (((res.add(j)).multiply(j)).compareTo(rem) <= 0) {
                    break;
                }
            }
            res = res.add(j);
            rem = rem.subtract(res.multiply(j));
            res = res.add(j);
            sb.append(j);
        }
        return new BigDecimal(sb.toString()).setScale(scale, roundingMode);
    }
    
    public static BigDecimal sqrt(BigDecimal number, int scale) {
        return sqrt(number, scale, BigDecimal.ROUND_HALF_UP);
    }
    
    public static BigDecimal sqrt(BigDecimal number) {
        int scale = number.scale() * 2;
        if (scale < 50)
            scale = 50;
        return sqrt(number, scale, BigDecimal.ROUND_HALF_UP);
    }

    static void initF(){
        f[0] = 0;f[1] = 1;
        for(int i = 2;true;i ++){
            f[i] = f[i - 1] + f[i - 2];
            if(f[i] > lim) break;
            cnt = i;
        }
    }
    
    static void get(int x)
    {
        if(x>0){a=f[x-1];b=f[x]; }
        else if(x==0){a=1;b=0;}
        else
        {
            x=-x;
            if(x%2==0){a=f[x-1];b=(-1)*f[x]; }
            else {a=(-1)*f[x-1];b=f[x]; }
        }
        return ;
    }
    
    public static void main(String args[]) {
        //System.out.println(new SimpleDateFormat("yyyy-mm-dd hh:mm:ss ms").format(new Date()));
        Scanner scanner=new Scanner(System.in);
        initF();
        BigDecimal five = BigDecimal.valueOf(5);
        BigDecimal w1 = sqrt(five, 20).add(BigDecimal.ONE).divide(BigDecimal.valueOf(2));
        BigDecimal w2 = sqrt(five, 20).subtract(BigDecimal.ONE).divide(BigDecimal.valueOf(2));
        BigDecimal w = null;
        BigDecimal eps = BigDecimal.valueOf(0.1);
        for(int i = 0;i < 10;i ++)eps = eps.multiply(BigDecimal.valueOf(0.1));
        //System.out.println(new SimpleDateFormat("yyyy-mm-dd hh:mm:ss ms").format(new Date()));
        while(scanner.hasNext()){
            BigDecimal n = scanner.nextBigDecimal();
            List<Integer> vec = new ArrayList<Integer>();
            w = w1;
            for(int i = cnt;n.compareTo(eps) > 0;i --){
                get(i);
                BigDecimal xx = BigDecimal.valueOf(a).add(BigDecimal.valueOf(b).multiply(w));
                if(n.compareTo(xx) < 0){
                    if(i == 0){
                        w = w2;
                    }
                    continue;
                }
                vec.add(i);
                n = n.subtract(xx);
                if(i == 0){
                    w = w2;
                }
            }
            String ans = "1";
            boolean flag = true;
            for(int i = 1;i < vec.size();i ++){
                int bef = vec.get(i - 1), now = vec.get(i);
                int d = bef - now - 1;
                if(now >= 0){
                    for(int j = 0;j < d;j ++)ans = ans + "0";
                } else {
                    if(bef >= 0){
                        for(int j = 0;j < bef;j ++){ans = ans + "0";d --;}
                    }
                    if(flag){ans = ans + ".";flag = false;}
                    for(int j = 0;j < d;j ++)ans = ans + "0";
                }
                ans = ans + "1";
            }
            System.out.println(ans);
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值