mayoko’s diary

プロコンとかいろいろ。

SRM 486 div1 easy: OneRegister

解法

s から t を考えるといろいろ可能性があって面倒ですが, t から s を考えれば,
・t が平方数 -> s は t の平方根
・t が偶数 -> s は t の半分
とほとんど場合分けがなくなり, また, t の遷移回数は 2^30 ≒ 10^9 より, たかだか 30 回程度です。30 回すべての場合で 平方根, 半分の両方の場合分けが生じることはありえないので, 基本的にこれで解けます。

初手で / を使って 1 にすることで s -> t に遷移できる可能性があることに注意です(サンプルにあるから気づくと思いますが)。

const int INF = 1e9;
string ans;
map<int, int> mp;

void dfs(int t, int s, string now) {
    if (t == s) {
        reverse(now.begin(), now.end());
        if (ans == "z" || ans.size() > now.size() || (ans.size() == now.size() && ans > now)) ans = now;
        return;
    }
    if (t == 1) {
        now += '/';
        reverse(now.begin(), now.end());
        if (ans == "z" || ans.size() > now.size() || (ans.size() == now.size() && ans > now)) ans = now;
        return;
    }
    if (mp.find(t) != mp.end()) {
        now += '*';
        dfs(mp[t], s, now);
        now.pop_back();
    }
    if (t%2 == 0) {
        now += '+';
        dfs(t/2, s, now);
        now.pop_back();
    }
}

class OneRegister {
public:
    string getProgram(int s, int t) {
        ans = "z";
        mp.clear();
        for (int i = 2; i*i <= INF; i++) mp[i*i] = i;
        dfs(t, s, "");
        if (ans == "z") ans = ":-(";
        return ans;
    }
};