第十二届蓝桥杯Java组真题-最少砝码-简单而高逼格的“对称三进制”

⚖️最少砝码

❓问题描述

你有一架天平。现在你要设计一套砝码,使得利用这些砝码可以称出任意 小于等于 NN 的正整数重量。

那么这套砝码最少需要包含多少个砝码?

注意砝码可以放在天平两边。

输入格式

输入包含一个正整数 N N N

输出格式

输出一个整数代表答案。

样例输入

7

样例输出

3

样例说明

3 个砝码重量是 1、4、6,可以称出 1 至 7的所有重量。

1 = 1;

2 = 6 − 4(天平一边放 66,另一边放 44);

3 = 4 − 1;

4 = 4;

5 = 6 − 1;

6 = 6;

7 = 1 + 6;

少于 3 个砝码不可能称出 1 至 7 的所有重量。

评测用例规模与约定

对于所有评测用例, 1 ≤ N ≤ 1000000000 1 ≤ N ≤ 1000000000 1N1000000000

运行限制

最大运行时间:1s

最大运行内存: 512M

题解

前提知识

这道题,如果固定一下,使得砝码只能在一边进行称重的话,那么题目会简单很多,大家一定可以很快的想到对于一个砝码,我们只有选和不选(1和0)两个状态,那么我们想要表示1-N中所有的重量的话,可以最少选择 [ l o g 2 ( N + 1 ) ] [log_2(N+1)] [log2(N+1)]个砝码就可以表示1-N中所有的重量了。

其实这个使用的是二进制的知识,比如说我们手上有1、2、4这三个砝码,那么我们就可以表示000、001、010、011、100、101、110、111这八种重量,其中000在这道题目中可以不计入重量,那么也就是可以表示1-7这七种重量,这个应该还是比较容易想到的

为什么是(N+1)为底?我们可以特殊化N=8时,那就需要4位来表示

但是很可惜,这道题多了一种状态,就是砝码是可以放在另一边来称重的,那么使用二进制就是无解了。。。。

知识点-三进制

于是!!!我们引入了三进制!!!

❓为什么是三进制?

我们这道题对于每个砝码其实有三个状态,也就是放到天平左侧,不放,放到天平右侧,这恰好可以对应三进制的三种状态:1,0,-1,因此三进制更符合于这道题的求解方案

❓三进制是啥?

其实大家听到三进制,第一反应都是用0,1,2三个数来表示数的进制方法,但是其实我们这道题目中使用的三进制是对称三进制(也称平衡三进制1),

❓平衡三进制如何与十进制进行转换?

首先我们需要知道,平衡三进制是由1,0,-1构成的,它的基数也是3(因为可能由三种值),由于-1写成数字不太方便,这里的-1我们都用Z来代替

我们先看看几种平衡三进制的表示:

平衡三进制 十进制
Z -1
0 0
1 1
ZZ -4
Z0 -3
Z1 -2
1Z 2
10 3
11 4

然后我们发现,平衡三进制是可以不重复地完整地表达 [ − 3 n − 1 2 , 3 n − 1 2 ] ( n ∈ Z ) [-\frac{3^n-1}{2},\frac{3^n-1}{2}](n\in Z) [23n1,23n1](nZ)中的每一个数的。

最终思路

所以,根据上面的思路,我们想要求出 1 − N 1-N 1N中的每一种重量,只需要求解出 3 n − 1 2 ≥ N \frac{3^n-1}{2}\geq N 23n1N,然后取 n n n的最小值即可。

我们解出来 n ≥ l o g 3 ( 2 N + 1 ) n\geq log_3(2N+1) nlog3(2N+1)

这就是我们的最终结果了

而我们也可以很容易地得出,我们所需要的砝码的重量⚓️分别为 1 、 3 、 9 ⋯ 3 n − 1 1、3、9\cdots3^{n-1} 1393n1

当然这上面只是数学的推导,我们写代码只需要枚举出这个 n n n的值就可以了

代码

package com.lanqiao;

import java.util.Scanner;

/**
 * @author 王宇哲
 * @date 2022/4/2 15:14
 */
public class 最少砝码 {

    /**
     * 需要能称出1-N中所有的重量
     */
    static int N;

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        N = scanner.nextInt();

        int n = 0;

        // 存储3^n的值,初始为3^0=1
        // 记得开long,否则会爆掉
        long num = 1;

        //通过枚举推到出一个n使得3^n>=2*N+1
        while (num < 2L * N + 1) {
            //找后面一个n
            n++;

            //得出3^n的值
            num *= 3;
        }

        System.out.println(n);

    }
}


  1. 平衡三进制,也称为对称三进制,是一种以3为基数,以-1,0,1为基本数码的三进制计数体系。俄罗斯科技人员曾经将其应用到计算机系统,也被应用于光子计算机相关研究中。 ↩︎

你可能感兴趣的:(蓝桥杯,算法,蓝桥杯,java)