奇妙货币交易问题题解

92 阅读2分钟

首先我们回顾一下题目

小R住在一个名为 X 国的国家,这里的货币非常特殊,面值为 V0,V1,V2,...,Vn V^0,V^1,V^2,...,V^n,并且 n 可以无限大。该国的交易规则也很特别:在一次交易中,双方只能对每种面值的货币使用不超过两次。

例如,小R想买一件价格为 198 的物品,货币的基数V=10 时,小R可以使用 2100(10210^2) 的纸币,卖家则找回2 张 1(10010^0)的纸币。由于这个奇怪的规则,很多 X 国人都无法快速判断某个物品是否可以用这种方式交易成功,他们常常会请聪明的你来帮助。

你能帮他们判断一下,是否能按照规则用给定的货币面值V来完成价格为 W 的交易吗?

解题思路

思路1

很多小伙伴拿到这题的第一反应就是上模拟,打一个深搜看看能不能匹配上最后的价格W

但这样的做法可能面临茫茫多的分支情况,面对每一种面额的货币都有±2,±1,0±2,±1,0(我们把付款一张此种面额的纸币记为+1,将找回此种面额的纸币记为-1,下文同)这五种情况,那么当价格较为庞大的时候可能面临的分支数会是以5为底数的指数级别增长,显然这样的处理量是我们负担不起的

思路2

由此我们可以尝试使用数学推理的办法来减少对于冗杂情况的模拟计算。

我们可以将关注的对象从价格W转移到货币上。

上面我们提到对于每种面额的货币,都只有±2,±1,0±2,±1,0这5种情况,倘若我们将买方和卖方综合起来考虑,对于每种面额的货币,对最终的价格影响就是±2,±1,0±2,±1,0这5种可能。那么不难得出这样的结论:

W=X0V0+X1V1+X2V2+X3V3++XnVnW=X_0V^0+X_1V^1+X_2V^2+X_3V^3+……+X_nV^n

其中Xi=(±2,±1,0)X_i=(±2,±1,0),也就是说现在的题目转变成了验证上面等式是否成立。这样是不是简单多了?我们只需要不断对W取模然后判断余数的范围是否是(0,1,2,Vn1V^n-1,Vn2V^n-2)即可

废话也不多说了,直接上代码

public class Main {
    public static String solution(int V, int W) {
        if (V ==1){
            return "YES";
        }
        String result="YES";
        int k;
        while (W>V) {
            while (W % V ==0) {
                W = W / V;
            }
            k = W % V;
            if (k>2 && k<V-2){
                result = "NO";
                break;
            }else {
                W-=k;
            }
        }
        k = W % V;
        if (k>2 && k<V-2){
            result = "NO";
        }
        return result;
    }

    public static void main(String[] args) {
        // Add your test cases here
        System.out.println(solution(10, 9).equals("YES"));
        System.out.println(solution(200, 40199).equals("YES"));
        System.out.println(solution(108, 50).equals("NO"));
    }
}