#P1226. 2023.04.15-春招-第一题-关于3
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 261
            Accepted: 93
            Difficulty: 5
            
          
          
          
                       所属公司 : 
                              米哈游
                                
            
                        
              时间 :2023年4月15日
                              
                      
          
 
- 
                        算法标签>数学          
 
2023.04.15-春招-第一题-关于3
题解:三进制+递归拆解
对于一个数字x,它一定可以表示为若干个2的整数幂的和,比如7=22+21+20,但是,它不一定能表示为若干个3的整数幂的和,比如30=33+31,这个是可以表示成若干个3的整数幂的和的,但是对于2这个数字来说,它不能被表示为若干个3的整数幂的和,但是可以被表示为26=33−30
那么我们分析一下:什么样的数字可以被表示为若干个3的整数幂的和,我们设i为3的整数幂的最高次幂,那么它可以表示的最大数字不超过30+31+...+3i=23i+1−1
因此,对于在该范围内的数字,是可以用若干个3的整数幂的和表示的,我们取i=log3(x),那如果有x≥23i+1−1,则我们需要向i+1借一位,然后让x=x−3i+1,然后再递归处理x,注意递归处理时,需要对x取绝对值,然后后面所得到的幂次也需要变换符号,比如加号变成减号,或者减号变成加号。
复杂度分析
时间复杂度:
O(logn)空间复杂度:
O(1)
C++
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
#define x first
#define y second
typedef long long ll;
const int N=1E5+10;
int n;
vector<int>nums;
ll pow(int a,int b)
{
    ll res=1,t=a;
    while(b)
    {
        if(b&1)res*=t;
        t*=t;
        b>>=1;
    }
    return res;
}
void get_val(int x)
{
    int t=1;
    while(x>1)
    {
        int p=log(x)/log(3);
        if((pow(3,p+1)-1)/2<x)   //不能由1 3 ... 3^p 表示 需要向上借位
        {
            nums.push_back(pow(3,p+1)*t);
            t*=-1;
            x=pow(3,p+1)-x;
        }
        else
        {
            nums.push_back(pow(3,p)*t);
            x-=pow(3,p);
        }
    }
    if(x)nums.push_back(x*t);
}
int main()
{
    // 1+3+...+3^n=(3^(n+1)-1)/2
    cin>>n;
    get_val(n);
    bool flag=true;
    for(int &x:nums)
    {
        if(flag)
        {
            cout<<x;
            flag=false;
        }
        else
        {
            if(x>0)cout<<"+";
            cout<<x;
        }
    }
    return 0;
}
Java
import java.util.*;
public class Main {
    static int n;
    static List<Integer> nums = new ArrayList<>();
    static long pow(int a, int b) {
        long res = 1, t = a;
        while (b > 0) {
            if ((b & 1) == 1) res *= t;
            t *= t;
            b >>= 1;
        }
        return res;
    }
    static void get_val(int x) {
        int t = 1;
        while (x > 1) {
            int p = (int) (Math.log(x) / Math.log(3));
            if ((pow(3, p + 1) - 1) / 2 < x) {
                nums.add((int) pow(3, p + 1) * t);
                t *= -1;
                x = (int) pow(3, p + 1) - x;
            } else {
                nums.add((int) pow(3, p) * t);
                x -= pow(3, p);
            }
        }
        if (x != 0) nums.add(x * t);
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        get_val(n);
        boolean flag = true;
        for (int x : nums) {
            if (flag) {
                System.out.print(x);
                flag = false;
            } else {
                if (x > 0) System.out.print("+");
                System.out.print(x);
            }
        }
    }
}
Python3
import math
def pow(a, b):
    res, t = 1, a
    while b:
        if b & 1:
            res *= t
        t *= t
        b >>= 1
    return res
def get_val(x):
    t = 1
    nums = []
    while x > 1:
        p = int(math.log(x) / math.log(3))
        if (pow(3, p + 1) - 1) / 2 < x:
            nums.append(pow(3, p + 1) * t)
            t *= -1
            x = pow(3, p + 1) - x
        else:
            nums.append(pow(3, p) * t)
            x -= pow(3, p)
    if x:
        nums.append(x * t)
    return nums
n = int(input())
nums = get_val(n)
flag = True
for x in nums:
    if flag:
        print(x, end='')
        flag = False
    else:
        if x > 0:
            print('+', end='')
        print(x, end='')
        题目内容
在这个古老的民族中,数学不仅是一门学科,更是一种信仰和文化。他们相信,数字是宇宙中最基本的构成元素,任何事物的本质都可以用数字来描述和解释。
因此,这个民族对数字的研究非常深入。他们探索各种数学问题,包括数论、几何、代数等等,不断推进数学领域的发展。
其中一个有趣的问题是如何用若干个不相等的 3 的幂次方的和或差来表示任何正整数。这个问题引起了这个民族数学家们的极大兴趣,经过长期的研究和探索,他们最终得出了结论:任何正整数都可以用若干个不相等的 3 的幂次方的和或差表示。
这个发现深深地影响了这个民族的文化和信仰,成为他们数学研究和文化传承中的重要组成部分。为了纪念这个发现,这个民族经常使用 3 的幂次方作为他们文化的象征,并且在重要的节日和庆典中经常使用这个数字来表示祝福和祈愿。
今天,你有机会帮助这个民族解决一个实际的问题:给定一个正整数,你需要找到一种由若干个不相等的 3 的幂次方的和或差表示的方式,并按照每一项从大到小的顺序输出。
输入描述
一个正整数 x 。 1≤x≤109
输出描述
一个表达式,最终的答案必须等于 x 。表达式的每一项必须是 3 的幂,且不能有两项相同。
例如, 18 必须输出为 27−9 而不能是 9+9 。
样例1
输入
30
输出
27+3
样例2
输入
300
输出
243+81-27+3