题目: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);
}
}
}