Project Euler #169: Exploring the number of different ways a number can be expressed as a sum of powers of 2.

题目

暴力破解

package com.company;
 
 
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;
 
 
public class Solution {
 
 
    public static void main(String[] args) {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
        Scanner in = new Scanner(System.in);
        int fn = in.nextInt();
        int n = (int) (Math.log((double) fn) / Math.log((double) 2));
        LinkedList<ArrayList<Integer>> outputList = new LinkedList<ArrayList<Integer>>();
 
 
        int size = (int) (Math.pow(3, n + 1));
        for (int i = 0; i < size; i++) {
            int number = i;
            ArrayList<Integer> innerList = new ArrayList<Integer>();
            for (int j = n; j >= 0; j--) {
                int div = (int) (Math.pow(3, j));
                int result = number / div;
                innerList.add(result);
                number = number % div;
            }
            outputList.add(innerList);
        }
 
 
        for (int i = 0; i < outputList.size(); i++) {
            int calculateResult = 0;
            for (int j = 0; j < outputList.get(i).size(); j++) {
                calculateResult += ((int) (Math.pow(2, outputList.get(i).size() - 1 - j))) * outputList.get(i).get(j);
            }
            if (calculateResult != fn) {
                outputList.remove(i);
                i = i - 1;
            }
        }
 
 
        System.out.println(outputList.size());
    }
}

递归

类似于斐波那契数列
if (n == 0)
return 1;
if (n % 2 ==1)
return f(n / 2) + f(n/2 - 1);
return f(n / 2);

package com.company;
 
 
import java.util.Scanner;
 
 
public class Solution {
    static long div2_total = 0;
    static long minus1_total = 0;
    static long f_total = 0;
    static long f1_total = 0;
    static long f2_total = 0;
    static long f3_total = 0;
 
 
    public static void main(String[] args) {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
        Scanner in = new Scanner(System.in);
        String n = in.nextLine();
        long time = System.currentTimeMillis();
        f(n);
        f_total = System.currentTimeMillis()-time;
        System.out.println("f_total="+f_total);
        System.out.println("div2_total="+div2_total);
        System.out.println("minus1_total="+minus1_total);
        System.out.println("other_total="+(f_total-div2_total-minus1_total));
        System.out.println("f1_total="+f1_total);
        System.out.println("f2_total="+f2_total);
        System.out.println("f3_total="+f3_total);
    }
 
 
    public static int f(String n) {
        char lastNum = n.charAt(n.length() - 1);
 
 
        if (n.equals("0")) {
            return 1;
        } else if ((lastNum == '0') ||
                (lastNum == '2') ||
                (lastNum == '4') ||
                (lastNum == '6') ||
                (lastNum == '8')) {
            return f(div2(n)) + f(div2minus1(n));
        } else {
            return f(div2(n));
        }
    }
 
 
    public static String div2(String n) {
        long time = System.currentTimeMillis();
        if (n.equals("1") || n.equals("0")) {
            div2_total += System.currentTimeMillis() - time;
            return "0";
        }
        String output = "";
        int tmp = 0;
        for (int i = 0; i < n.length(); i++) {
            if (!(i == 0 && ((tmp * 10 + Integer.parseInt(String.valueOf(n.charAt(i)))) / 2) == 0)) {
                output = output + ((tmp * 10 + Integer.parseInt(String.valueOf(n.charAt(i)))) / 2);
            }
            if (i != (n.length() - 1) && ((tmp * 10 + Integer.parseInt(String.valueOf(n.charAt(i)))) % 2 != 0)) {
                tmp = 1;
            } else {
                tmp = 0;
            }
        }
        div2_total += System.currentTimeMillis() - time;
        return output;
    }
 
 
    public static String div2minus1(String n) {
        String output = div2(n);
        return minus1(output);
    }
 
 
    public static String minus1(String n) {
        long time = System.currentTimeMillis();
        if (n.equals("1") || n.equals("0")) {
            return "0";
        }
 
 
        int[] numbers = new int[n.length()];
        for (int i = 0; i < n.length(); i++) {
            numbers[i] = Integer.parseInt(n.charAt(i) + "");
        }
        if (numbers[numbers.length - 1] == 0) {
            for (int i = numbers.length - 1; i >= 0; i--) {
                if (numbers[i] != 0) {
                    numbers[i] = numbers[i] - 1;
                    for (int j = i + 1; j < numbers.length; j++) {
                        numbers[j] = 9;
                    }
                    break;
                }
            }
        } else {
            numbers[numbers.length - 1] = numbers[numbers.length - 1] - 1;
        }
        String output = "";
        boolean isHead = true;
        for (int i = 0; i < numbers.length; i++) {
            if (isHead) {
                if (numbers[i] == 0) {
                    continue;
                } else {
                    isHead = false;
                }
            }
            output += numbers[i];
        }
        minus1_total += System.currentTimeMillis() - time;
        return output;
    }
}

官方答案

package com.company;
 
 
import java.math.BigInteger;
import java.util.*;
 
 
public final class Solution {
 
 
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String n = in.nextLine();
        System.out.println(new Solution().run(new BigInteger(n)));
    }
 
 
    public String run(BigInteger number) {
        return countWays(number, number.bitLength() - 1, 2).toString();
    }
 
 
 
 
   /*
    * ways(n, i, j) is the number of ways that the number n can be expressed as
    * an unordered sum of powers of 2 such that all these conditions are true:
    * - The highest possible power is 2^i
    * - The 2^i term is used between 0 and j times
    * - All lower powers of 2 are used no more than 2 times
    */
 
 
    // Memoization
    private Map<List<BigInteger>,BigInteger> ways = new HashMap<>();
 
 
    private BigInteger countWays(BigInteger number, int exponent, int repetitions) {
        List<BigInteger> key = Arrays.asList(number, BigInteger.valueOf(exponent), BigInteger.valueOf(repetitions));
        if (ways.containsKey(key))
            return ways.get(key);
 
 
        BigInteger result;
        if (exponent < 0)
            result = number.equals(BigInteger.ZERO) ? BigInteger.ONE : BigInteger.ZERO;
        else {
            result = countWays(number, exponent - 1, 2);
            BigInteger pow = BigInteger.ONE.shiftLeft(exponent);
            BigInteger upper = pow.multiply(BigInteger.valueOf(repetitions + 2));
            if (repetitions > 0 && pow.compareTo(number) <= 0 && number.compareTo(upper) < 0)
                result = result.add(countWays(number.subtract(pow), exponent, repetitions - 1));
        }
        ways.put(key, result);
        return result;
    }
  
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,743评论 0 33
  • 假设第1个月有1对刚诞生的兔子,第2个月进入成熟期,第3个月开始生育兔子,而1对成熟的兔子每月会生1对兔子,兔子永...
    rainchxy阅读 8,081评论 0 1
  • 原文出处:http://www.cnblogs.com/maybe2030/p/4715035.html引文出处:...
    明教de教主阅读 9,162评论 0 7
  • 2017年5月18日,天气晴。今天和儿子看了一篇关于脑瘫孩子考进哈佛的报道,在我儿子的意识里不太明白什么是脑瘫,他...
    宋颢然妈妈阅读 192评论 0 2
  • 这几天在复习教师资格证的考试,其中一章的内容是关于中学生学习心理的。第一遍看的时候,我感慨学习其实是一个养成习惯的...
    Bingo爱吃饭阅读 492评论 0 0