java算法集训结果填空题练习2

1 欧拉与鸡蛋

大数学家欧拉在集市上遇到了本村的两个农妇,每人跨着个空篮子。她们和欧拉打招呼说两人刚刚卖完了所有的鸡蛋。
欧拉随便问:“卖了多少鸡蛋呢?”
不料一个说:“我们两人自己卖自己的,一共卖了150个鸡蛋,虽然我们卖的鸡蛋有多有少,但刚好得了同样的钱数。你猜猜看!”
欧拉猜不出。
另一个补充道:“如果我按她那样的价格卖,可以得到32元;如果她按我的价格卖,可以得到24.5元”。
欧拉想了想,说出了正确答案。

我们不是数学家,懒得列出公式来分析。但计算机可以“暴力破解”,就是把所有可能情况都试验一遍,撞上为止!
请写出每人鸡蛋的数目(顺序不限),用逗号隔开。

答案写在“解答.txt”中,不要写在这里!

参考答案:
70,80 或 80,70

public class Main {
    
    public static void main(String[] args) {
        for(int x = 1;x < 150;x++) {
            int y = 150 - x;
            for(double a = 0.2;a <= 0.5;a = a + 0.001) {
                for(double b = 0.2;b <= 0.5;b = b + 0.001) {
                    if(a * x == b * y) {
                        if(a * y > 31 && a * y < 33 && b * x > 23 && b * x < 25 ) {
                            System.out.println(x+", "+a+", "+y+", "+b);
                            System.out.println(a*y+", "+b*x);
                        }
                    }
                }
            }
        }
    }
}

2 巧排扑克牌

小明刚上小学,学会了第一个扑克牌“魔术”,到处给人表演。魔术的内容是这样的:
他手里握着一叠扑克牌:A,2,…J,Q,K 一共13张。他先自己精心设计它们的顺序,然后正面朝下拿着,开始表演。
只见他先从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是A;然后再从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是2;…如此循环直到手中只有一张牌,翻开放桌子上,刚好是K。
这时,桌上牌的顺序是:A,2,3,4,5,6,7,8,9,10,J,Q,K
请你计算一下,小明最开始的时候手里牌的顺序是怎样的。
把结果写出来,逗号分割,小明“魔术”开始时,最下面的那张牌输出为第一个数据。
考场不提供扑克牌,你只能用计算机模拟了,撕碎草稿纸模拟扑克属于作弊行为!另外,你有没有把录像倒着放过?很有趣的!回去试试!

参考答案:
7, A, Q, 2, 8, 3, J, 4, 9, 5, K, 6, 10

public class Main1 {
    
    public void printResult(char[] A) {
        char[] result = new char[A.length];
        boolean[] used = new boolean[A.length];
        for(int i = 0;i < A.length;i++)
            used[i] = false;
        int count = 0, j = -1;
        for(int i = 0;i < A.length;i++) {
            for(;;) {
                j = (j + 1) % A.length;
                if(count < 2) {
                    if(used[j] == false)
                        count++;
                }
                
                if(count == 2) {
                    result[j] = A[i];
                    used[j] = true;
                    count = 0;
                    break;
                }
                
            }
        }
        
        for(int i = 0;i < A.length;i++)
            System.out.print(result[i]+" ");
        return;
    }
    
    public static void main(String[] args) {
        Main1 test = new Main1();
        //下面字符'a'代表数字10
        char[] A = {'A','2','3','4','5','6','7','8','9','a','J','Q','K'};
        test.printResult(A);
    }
}

3 排座位

要安排:3个A国人,3个B国人,3个C国人坐成一排。
要求不能使连续的3个人是同一个国籍。
求所有不同方案的总数?

参考答案:
283824

public class Main1 {
    
    public static int count = 0;
    
    public void swap(int[] A, int a, int b) {
        int temp = A[a];
        A[a] = A[b];
        A[b] = temp;
    }
    
    public void dfs(int[] A, int step) {
        if(step == A.length) {
            if(check(A))
                count++;
            return;
        } else {
            for(int i = step;i < A.length;i++) {
                swap(A, i, step);
                dfs(A, step + 1);
                swap(A, i, step);
            }
        }
        return;
    }
    
    public boolean check(int[] A) {
        for(int i = 2;i < A.length;i++) {
            if(A[i] == A[i - 1] && A[i] == A[i - 2])
                return false;
        }
        return true;
    }
    
    public static void main(String[] args) {
        Main1 test = new Main1();
        int[] A = {1,1,1,2,2,2,3,3,3};
        test.dfs(A, 0);
        System.out.println(count);
    }
}

4 黄金队列

黄金分割数0.618与美学有重要的关系。舞台上报幕员所站的位置大约就是舞台宽度的0.618处,墙上的画像一般也挂在房间高度的0.618处,甚至股票的波动据说也能找到0.618的影子…
黄金分割数是个无理数,也就是无法表示为两个整数的比值。0.618只是它的近似值,其真值可以通过对5开方减去1再除以2来获得,我们取它的一个较精确的近似值:0.618034
有趣的是,一些简单的数列中也会包含这个无理数,这很令数学家震惊!
1 3 4 7 11 18 29 47 … 称为“鲁卡斯队列”。它后面的每一个项都是前边两项的和。
如果观察前后两项的比值,即:1/3,3/4,4/7,7/11,11/18 … 会发现它越来越接近于黄金分割数!
你的任务就是计算出从哪一项开始,这个比值四舍五入后已经达到了与0.618034一致的精度。
请写出该比值。格式是:分子/分母。比如:29/47
答案写在“解答.txt”中,不要写在这里!

参考答案:
1364/2207

public class Main1 {
    
    public static void main(String[] args) {
        int a = 1, b = 3;
        for(int i = 3;i < 40;i++) {
            int temp = a + b;
            a = b;
            b = temp;
            double result = a * 1.0 / b;
            String A = String.format("%.6f", result);
            result = Double.valueOf(A);
            if(result == 0.618034) {
                System.out.println(a+", "+b);
                break;
            }
        }
    }
}

5 汉诺塔计数

汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上(可以借助第三根柱子做缓冲)。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
如图【1.jpg】是现代“山寨”版的该玩具。64个圆盘太多了,所以减为7个,金刚石和黄金都以木头代替了…但道理是相同的。
据说完成大梵天的命令需要太多的移动次数,以至被认为完成之时就是世界末日!
你的任务是精确计算出到底需要移动多少次。
很明显,如果只有2个圆盘,需要移动3次。
圆盘数为3,则需要移动7次。
那么64个呢?
答案写在“解答.txt”中,不要写在这里!

图1

参考答案:
18446744073709551615

import java.math.BigInteger;

public class Main1 {
    
    public static void main(String[] args) {
        BigInteger a = BigInteger.ONE;
        BigInteger b = new BigInteger("2");
        for(int i = 1;i <= 64;i++)
            a = a.multiply(b);
        a = a.subtract(BigInteger.ONE);
        System.out.println(a);
    }
}

6 猜生日

今年的植树节(2012年3月12日),小明和他的叔叔还有小伙伴们一起去植树。休息的时候,小明的同学问他叔叔多大年纪,他叔叔说:“我说个题目,看你们谁先猜出来!”
“把我出生的年月日连起来拼成一个8位数(月、日不足两位前补0)正好可以被今天的年、月、日整除!”
他想了想,又补充到:“再给个提示,我是6月出生的。”
根据这些信息,请你帮小明算一下,他叔叔的出生年月日。
答案写在“解答.txt”中,不要写在这里!

格式是年月日连成的8位数。
例如,如果是1948年6月12日,就写:19480612

参考答案:
19550604

public class Main1 {
    
    public static void main(String[] args) {
        for(int i = 19000000;i < 19990000;i++) {
            if(i % 2012 == 0 && i % 3 == 0 && i % 12 == 0) {
                int temp = i / 100 % 10;
                int temp1 = i / 1000 % 10;
                if(temp == 6 && temp1 == 0)
                    System.out.println(i);
            }
        }
    }
}

7 棋盘上的麦子

你一定听说过这个故事。国王对发明国际象棋的大臣很佩服,问他要什么报酬,大臣说:请在第1个棋盘格放1粒麦子,在第2个棋盘格放2粒麦子,在第3个棋盘格放4粒麦子,在第4个棋盘格放8粒麦子,…后一格的数字是前一格的两倍,直到放完所有棋盘格(国际象棋共有64格)。
国王以为他只是想要一袋麦子而已,哈哈大笑。
当时的条件下无法准确计算,但估算结果令人吃惊:即使全世界都铺满麦子也不够用!
请你借助计算机准确地计算,到底需要多少粒麦子。

答案写在“解答.txt”中,不要写在这里!

参考答案:
18446744073709551615

import java.math.BigInteger;

public class Main1 {
    
    public static void main(String[] args) {
        BigInteger a = BigInteger.ONE;
        BigInteger b = new BigInteger("2");
        for(int i = 1;i <= 64;i++)
            a = a.multiply(b);
        a = a.subtract(BigInteger.ONE);
        System.out.println(a);
    }
}

8 国庆星期日

1949年的国庆节(10月1日)是星期六。
今年(2012)的国庆节是星期一。
那么,从建国到现在,有几次国庆节正好是星期日呢?
只要答案,不限手段!
可以用windows日历,windows计算器,Excel公式,。。。。。
当然,也可以编程!
不要求写出具体是哪些年,只要一个数目!
千万不要提交源代码!
答案不要写在这里,写在“解答.txt”中

参考答案:
9

public class Main1 {
    
    public void printResult() {
        int day = 0;
        int count = 0;
        for(int i = 1950;i <= 2012;i++) {
            int a = 365;
            if(i % 400 == 0 || (i % 4 == 0 && i % 100 != 0))
                a = 366;
            day += a;
            if(day % 7 == 1)
                count++;
        }
        System.out.println(count);
        return;
    }
    
    public static void main(String[] args) {
        Main1 test = new Main1();
        test.printResult();
    }
}

9 找素数

素数就是不能再进行等分的整数。比如:7,11。而9不是素数,因为它可以平分为3等份。一般认为最小的素数是2,接着是3,5,…
请问,第100002(十万零二)个素数是多少?
请注意:“2” 是第一素数,“3” 是第二个素数,依此类推。
不需要提交源代码,只要写出准确的结果即可!
答案写在:“解答.txt”中,不要写在这里。

参考答案:
1299743

import java.math.BigInteger;

public class Main1 {
    //方法1:使用大整数,自带判断素数方法,算出最终结果大约要1分钟
    public void printResult1() {
        int count = 1;
        BigInteger a = new BigInteger("3");
        BigInteger b = BigInteger.ONE;
        for(int i = 3;i < 10000000;i++){
            if(a.isProbablePrime(i)) {
                count++;
            }
            if(count == 100002) {
                System.out.println(a);
                break;
            }
            a = a.add(b);
        }
        return;
    }
    
    //方法2:使用埃拉托色尼筛选法,算出结果大约10秒
    public void printResult2() {
        int[] A = new int[10000000];
        for(int i = 2;i < 10000000;i++)
            A[i] = i;
        
        for(int i = 2;i < 4000;i++) { // 4000 * 4000 > 10000000,此处是因为i*i为i的当前条件下最小合数
            int j = 0;
            if(A[i] != 0)
                j = i * i;  //i的合数起始最小位置
            while(j < 10000000) {
                A[j] = 0;
                j = j + i;   //依次递增i个位置的数均是i的合数
            }
            
        }
        
        int count = 0;
        for(int i = 2;i < 10000000;i++) {
            if(A[i] != 0) 
                count++;
            if(count == 100002) {
                System.out.println(A[i]);
                break;
            }
        }
        return;
    }
    
    public static void main(String[] args) {
        Main1 test = new Main1();
        test.printResult2();
    }
}

10 填写算式

看这个算式:
☆☆☆ + ☆☆☆ = ☆☆☆
如果每个五角星代表 1 ~ 9 的不同的数字。
这个算式有多少种可能的正确填写方法?
173 + 286 = 459
295 + 173 = 468
173 + 295 = 468
183 + 492 = 675
以上都是正确的填写法!
注意:
111 + 222 = 333 是错误的填写法!
因为每个数字必须是不同的!
也就是说:1~9中的所有数字,每个必须出现且仅出现一次!
注意:
不包括数字“0”!
注意:
满足加法交换率的式子算两种不同的答案。
所以答案肯定是个偶数!

注意:
只要求计算不同的填法的数目
不要求列出所有填写法
更不要求填写源代码!

答案不要写在这里,请写在“解答.txt”中!

参考答案:
336

public class Main1 {
    
    public static int count = 0;
    
    public void swap(int[] A, int a, int b) {
        int temp = A[a];
        A[a] = A[b];
        A[b] = temp;
    }
    
    public void dfs(int[] A, int step) {
        if(step == A.length) {
            check(A);
            return;
        } else {
            for(int i = step;i < A.length;i++) {
                swap(A, i, step);
                dfs(A, step + 1);
                swap(A, i, step);
            }
        }
        return;
    }
    
    public void check(int[] A) {
        String tempA = "";
        for(int i = 0;i < A.length;i++)
            tempA += A[i];
        int a = Integer.valueOf(tempA.substring(0, 3));
        int b = Integer.valueOf(tempA.substring(3, 6));
        int c = Integer.valueOf(tempA.substring(6, 9));
        if(a + b == c)
            count++;
        return;
    }
    
    public static void main(String[] args) {
        Main1 test = new Main1();
        int[] A = {1,2,3,4,5,6,7,8,9};
        test.dfs(A, 0);
        System.out.println(count);
    }
}

11 取字母组成串

A B C D中取5次,每个字母都可以重复取出,形成一个串。
现在要求,串中A出现的次数必须为偶数(0次也算偶数)。
求可以形成多少种可能的串。

参考答案:
528

public class Main1 {
    
    public static boolean judge(int[] A) {
        int count = 0;
        for(int i = 0;i < A.length;i++) {
            if(A[i] == 1)
                count++;
        }
        if(count == 0 || count % 2 == 0)
            return true;
        return false;
    }
    
    public static void main(String[] args) {
        int[] A = {1,2,3,4};  //1234分别代表ABCD
        int[] tempA = new int[5];
        int count = 0;
        for(int a = 0;a < 4;a++) {
            tempA[0] = A[a];
            for(int b = 0;b < 4;b++) {
                tempA[1] = A[b];
                for(int c = 0;c < 4;c++) {
                    tempA[2] = A[c];
                    for(int d = 0;d < 4;d++) {
                        tempA[3] = A[d];
                        for(int e = 0;e < 4;e++) {
                            tempA[4] = A[e];
                            if(judge(tempA))
                                count++;
                        }
                    }
                }
            }
        }
        System.out.println(count);
    }
}
posted @ 2019-07-23 19:05  南墙1  阅读(21)  评论(0编辑  收藏  举报