Search on the blog

2011年11月23日水曜日

SRM 524 DIV2 1000 multipleswithlimit

modular arithmeticの絡んだ数論チックな問題(好きなタイプの問題)。余り毎にメモ化しておけばいいのはすぐ気付いたけど、最初のsubmissionでは、dp[2][10000]みたいにして、rolling table/flying tableを使って解いて、TLE。前回新しく更新されたところだけをpick upすればいいので、priority_queueを利用したダイクストラ法のようなやり方をすればいいのに気付く。これでAC。

(追記)editorial読んだら、queueでいいっぽい。最初に埋まったやつがbestになるから、確かにqueueでOK。


typedef pair<int, pair<string, int> >  ISI;
string dp[10000];

class MultiplesWithLimit {
    string format(string x) {
        if (x.length() < 9)
            return x;

        char ret[512];
        sprintf(ret, "%s...%s(%d digits)", x.substr(0, 3).c_str(), x.substr(x.length()-3).c_str(), x.length());

        return ret;
    }

    bool contain(vector<int> vec, int n) {
        REP(i, vec.size())
            if (vec[i] == n)
                return true;

        return false;
    }

public:
    string minMultiples(int N, vector<int> forbiddenDigits) {
        vector<int> nums;

        REP(i, 10) {
            if (!contain(forbiddenDigits, i))
                nums.push_back(i);
        }

        priority_queue<ISI, vector<ISI>, greater<ISI> > Q;
        Q.push(MP(0, MP("", 0)));
        string ret = "";

        REP(i, 10000) dp[i] = "";
        while (!Q.empty()) {
            string str = Q.top().second.first;
            int rm = Q.top().second.second;

            Q.pop();
            if (rm == 0 && str != "") {
                ret = str;
                break;
            }
            if (dp[rm].length() < str.length() ||
                (dp[rm].length() == str.length() && dp[rm] < str))
                continue;

            REP(i, nums.size()) {
                int rm_t = (10 * rm + nums[i]) % N;
                string str_t = str + (char)(nums[i] + '0');

                if (str_t == "0") continue;
                if (dp[rm_t] == "" ||
                 str_t.length() < dp[rm_t].length() ||
                 (str_t.length() == dp[rm_t].length() && str_t < dp[rm_t])
                ) {
                    dp[rm_t] = str_t;
                    Q.push(MP(str_t.length(), MP(str_t, rm_t)));
                }
            }
        }

        if (ret == "")
            return "IMPOSSIBLE";

        return format(ret);
    }
};


0 件のコメント:

コメントを投稿