結果

問題 No.5003 物理好きクリッカー
ユーザー maimai
提出日時 2018-12-08 10:49:50
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 33 ms / 10,000 ms
コード長 16,682 bytes
コンパイル時間 3,001 ms
実行使用メモリ 22,008 KB
スコア 92,179,776,007
平均クエリ数 10000.00
最終ジャッジ日時 2021-07-19 09:10:09
合計ジャッジ時間 6,628 ms
ジャッジサーバーID
(参考情報)
judge11 / judge12
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 32 ms
21,864 KB
testcase_01 AC 32 ms
21,540 KB
testcase_02 AC 31 ms
21,372 KB
testcase_03 AC 32 ms
21,528 KB
testcase_04 AC 33 ms
21,492 KB
testcase_05 AC 32 ms
21,372 KB
testcase_06 AC 32 ms
21,336 KB
testcase_07 AC 33 ms
21,516 KB
testcase_08 AC 33 ms
21,528 KB
testcase_09 AC 32 ms
21,852 KB
testcase_10 AC 33 ms
21,216 KB
testcase_11 AC 32 ms
21,360 KB
testcase_12 AC 32 ms
21,840 KB
testcase_13 AC 32 ms
21,492 KB
testcase_14 AC 31 ms
21,360 KB
testcase_15 AC 32 ms
21,528 KB
testcase_16 AC 33 ms
21,876 KB
testcase_17 AC 32 ms
21,492 KB
testcase_18 AC 32 ms
21,528 KB
testcase_19 AC 32 ms
21,480 KB
testcase_20 AC 32 ms
21,672 KB
testcase_21 AC 32 ms
21,492 KB
testcase_22 AC 32 ms
21,540 KB
testcase_23 AC 32 ms
21,840 KB
testcase_24 AC 32 ms
21,336 KB
testcase_25 AC 32 ms
21,516 KB
testcase_26 AC 32 ms
21,684 KB
testcase_27 AC 32 ms
21,360 KB
testcase_28 AC 32 ms
21,480 KB
testcase_29 AC 33 ms
21,744 KB
testcase_30 AC 32 ms
21,492 KB
testcase_31 AC 32 ms
21,864 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: 関数 ‘char* machineToString(EMachine)’ 内:
main.cpp:144:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  144 |         "hand",
      |         ^~~~~~
main.cpp:145:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  145 |         "lily",
      |         ^~~~~~
main.cpp:146:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  146 |         "factory",
      |         ^~~~~~~~~
main.cpp:147:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  147 |         "casino",
      |         ^~~~~~~~
main.cpp:148:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  148 |         "grimoire"
      |         ^~~~~~~~~~
main.cpp: メンバ関数 ‘void Action::print() const’ 内:
main.cpp:177:24: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  177 |             printer << "click\n";
      |                        ^~~~~~~~~
main.cpp:180:24: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  180 |             printer << "buy " << machineToString(target) << '\n';
      |                        ^~~~~~
main.cpp:184:28: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  184 |                 printer << "enhclick\n";
      |                            ^~~~~~~~~~~~
main.cpp:186:28: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  186 |                 printer << "reinforce " << machineToString(target) << '\n';
      |                            ^~~~~~~~~~~~
main.cpp:189:24: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  189 |             printer << "sell " << machineToString(target) << '\n';
      |                        ^~~~~~~

ソースコード

diff #

#pragma GCC optimize ("O3")
// #pragma GCC target ("avx")
#include "bits/stdc++.h"

using namespace std;
using ll = long long int;

#define debugos cout
#define debug(v) {printf("L%d %s > ",__LINE__,#v);debugos<<(v)<<endl;}
#define debugv(v) {printf("L%d %s > ",__LINE__,#v);for(auto e:(v)){debugos<<e<<" ";}debugos<<endl;}
#define debuga(m,w) {printf("L%d %s > ",__LINE__,#m);for(int x=0;x<(w);x++){debugos<<(m)[x]<<" ";}debugos<<endl;}
#define debugaa(m,h,w) {printf("L%d %s >\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){debugos<<(m)[y][x]<<" ";}debugos<<endl;}}
#define ALL(v) (v).begin(),(v).end()
#define repeat(cnt,l) for(auto cnt=decltype(l)();(cnt)<(l);++(cnt))
#define rrepeat(cnt,l) for(auto cnt=(l)-1;0<=(cnt);--(cnt))
#define iterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);++(cnt))
#define diterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);--(cnt))
const ll MD = 1000000007ll; const long double PI = 3.1415926535897932384626433832795L;
inline void assert_call(bool assertion, function<void()> f) { if (!assertion) { cerr << "assertion fault:" << endl; f(); abort(); } }
template<typename T1, typename T2> inline ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << '(' << p.first << ':' << p.second << ')'; return o; }
template<typename Vec> inline ostream& _ostream_vecprint(ostream& os, const Vec& a) {
    os << '['; for (const auto& e : a) os << ' ' << e << ' '; os << ']'; return os;
}
template<typename T> inline ostream& operator<<(ostream& o, const vector<T>& v) { return _ostream_vecprint(o, v); }
template<typename T, size_t S> inline ostream& operator<<(ostream& o, const array<T, S>& v) { return _ostream_vecprint(o, v); }
template<typename T> inline T& chmax(T& to, const T& val) { return to = max(to, val); }
template<typename T> inline T& chmin(T& to, const T& val) { return to = min(to, val); }
void bye(string s, int code = 0) { cout << s << endl; exit(code); }
mt19937_64 randdev(8901016);
template<typename T, typename Random = decltype(randdev), typename enable_if<is_integral<T>::value>::type* = nullptr>
inline T rand(T l, T h, Random& rand = randdev) { return uniform_int_distribution<T>(l, h)(rand); }
template<typename T, typename Random = decltype(randdev), typename enable_if<is_floating_point<T>::value>::type* = nullptr>
inline T rand(T l, T h, Random& rand = randdev) { return uniform_real_distribution<T>(l, h)(rand); }


#if defined(_WIN32) || defined(_WIN64)
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#elif defined(__GNUC__)
#else
#define getchar_unlocked getchar
#define putchar_unlocked putchar
#endif
namespace {
#define isvisiblechar(c) (0x21<=(c)&&(c)<=0x7E)
    class MaiScanner {
    public:
        template<typename T> void input_integer(T& var) noexcept {
            var = 0; T sign = 1;
            int cc = getchar_unlocked();
            for (; cc < '0' || '9' < cc; cc = getchar_unlocked())
                if (cc == '-') sign = -1;
            for (; '0' <= cc && cc <= '9'; cc = getchar_unlocked())
                var = (var << 3) + (var << 1) + cc - '0';
            var = var * sign;
        }
        inline int c() noexcept { return getchar_unlocked(); }
        inline MaiScanner& operator>>(int& var) noexcept { input_integer<int>(var); return *this; }
        inline MaiScanner& operator>>(long long& var) noexcept { input_integer<long long>(var); return *this; }
        inline MaiScanner& operator>>(string& var) {
            int cc = getchar_unlocked();
            for (; !isvisiblechar(cc); cc = getchar_unlocked());
            for (; isvisiblechar(cc); cc = getchar_unlocked())
                var.push_back(cc);
            return *this;
        }
        template<typename IT> inline void in(IT begin, IT end) { for (auto it = begin; it != end; ++it) *this >> *it; }
    };
    class MaiPrinter {
    public:
        template<typename T>
        void output_integer(T var) noexcept {
            if (var == 0) { putchar_unlocked('0'); return; }
            if (var < 0)
                putchar_unlocked('-'),
                var = -var;
            char stack[32]; int stack_p = 0;
            while (var)
                stack[stack_p++] = '0' + (var % 10),
                var /= 10;
            while (stack_p)
                putchar_unlocked(stack[--stack_p]);
        }
        inline MaiPrinter& operator<<(char c) noexcept { putchar_unlocked(c); return *this; }
        inline MaiPrinter& operator<<(int var) noexcept { output_integer<int>(var); return *this; }
        inline MaiPrinter& operator<<(long long var) noexcept { output_integer<long long>(var); return *this; }
        inline MaiPrinter& operator<<(char* str_p) noexcept { while (*str_p) putchar_unlocked(*(str_p++)); return *this; }
        inline MaiPrinter& operator<<(const string& str) {
            const char* p = str.c_str();
            const char* l = p + str.size();
            while (p < l) putchar_unlocked(*p++);
            return *this;
        }
        template<typename IT> void join(IT begin, IT end, char sep = ' ') { for (bool b = 0; begin != end; ++begin, b = 1) b ? *this << sep << *begin : *this << *begin; }
    };
}
MaiScanner scanner;
MaiPrinter printer;

// 

template<typename T1, typename T2>
struct Tag {

    T1 first; T2 second;

    Tag(T1 t1, T2 t2) :first(t1), second(t2) {}
    Tag(const pair<T1, T2>& p) :first(p.first), second(p.second) { }
    Tag(const pair<T1, T2>&& p) :first(p.first), second(p.second) { }

    inline bool operator == (const Tag& t) const {
        return first == t.first;
    }
    inline bool operator <(const Tag& t) const {
        return first < t.first;
    }
};


//


enum EMachine {
    kHand = 0, kLily, kFactory, kCasino, kGrimoire, kClicker
};

enum ECommand {
    kClick = 0,
    kBuy,
    kReinforce,
    kSell
};

enum EEffect {
    kNothing = 0,
    kBonus,
    kFever,
    kSale
};


inline char* machineToString(EMachine m) {
    static char* s[] = {
        "hand",
        "lily",
        "factory",
        "casino",
        "grimoire"
    };
    return s[(int)m];
}


inline EEffect charToEffect(char c) {
    return
        c == 'N' ? EEffect::kNothing :
        c == 'B' ? EEffect::kBonus :
        c == 'F' ? EEffect::kFever :
        c == 'S' ? EEffect::kSale : EEffect::kNothing;
}


//


struct Action {
    ECommand command;
    EMachine target;
    Action(ECommand aCommand = ECommand::kClick, EMachine aTarget = EMachine::kHand)
        :command(aCommand), target(aTarget) {
    }

    void print() const {
        switch (command)
        {
        case kClick:
            printer << "click\n";
            break;
        case kBuy:
            printer << "buy " << machineToString(target) << '\n';
            break;
        case kReinforce:
            if (target == EMachine::kClicker)
                printer << "enhclick\n";
            else
                printer << "reinforce " << machineToString(target) << '\n';
            break;
        case kSell:
            printer << "sell " << machineToString(target) << '\n';
            break;
        default:
            clog << "invalid command\n";
            break;
        }
    }
};


class State {

    ll wallet_;
    array<int, 6> numMachine_;
    array<int, 6> lvlMachine_;
    array<ll, 5> costBuyMachine_ = { 150ll, 2000ll, 30000ll, 600000ll, 10000000ll };
    array<ll, 6> costRfMachine_ = { 1500ll, 20000ll, 300000ll, 6000000ll, 100000000ll, 15ll };

public:

    State() :wallet_(0) {
        numMachine_.fill(0);
        numMachine_[5] = 1;
        lvlMachine_.fill(0);
    }

    static ll discount(ll cost) noexcept {
        return (cost * 9 + 9) / 10;
    }

    //
    inline ll costBuyMachine(EMachine e) const {
        return costBuyMachine_[(int)e];
    }
    inline ll costReinforceMachine(EMachine e) const {
        return costRfMachine_[(int)e];
    }
    inline ll wallet() const {
        return wallet_;
    }
    inline int countOfMachine(EMachine e) const {
        return numMachine_[(int)e];
    }

    //
    inline bool buyableMachine(EMachine e, bool sale = false) const {
        return sale ?
            discount(costBuyMachine_[(int)e]) <= wallet_ :
            costBuyMachine_[(int)e] <= wallet_;
    }
    inline bool reinforceableMachine(EMachine e, bool sale = false) const {
        return sale ?
            discount(costRfMachine_[(int)e]) <= wallet_ :
            costRfMachine_[(int)e] <= wallet_;
    }

    //
    inline ll efficiency(EMachine e) const {
        const ll s[] = { 1, 10, 120, 2000, 25000, 1 };
        return s[(int)e] * (1ll << lvlMachine_[(int)e])*numMachine_[(int)e];
    }
    inline ll nextLevelEfficiency(EMachine e) const {
        const ll s[] = { 1, 10, 120, 2000, 25000, 1 };
        return s[(int)e] * (1ll << (lvlMachine_[(int)e] + 1))*numMachine_[(int)e];
    }
    inline ll oneMoreEfficiency(EMachine e) const {
        const ll s[] = { 1, 10, 120, 2000, 25000, 1 };
        return s[(int)e] * (1ll << lvlMachine_[(int)e])*(numMachine_[(int)e] + 1);
    }

    void applyAction(Action act, EEffect eff) {
        if (act.command == ECommand::kClick) {
        }
        else if (act.command == ECommand::kBuy) {
            numMachine_[act.target] += 1;
            wallet_ -= eff == EEffect::kSale ? discount(costBuyMachine_[act.target]) : costBuyMachine_[act.target];
            costBuyMachine_[act.target] = (costBuyMachine_[act.target] * 6 + 4) / 5;
        }
        else if (act.command == ECommand::kReinforce) {
            lvlMachine_[act.target] += 1;
            wallet_ -= eff == EEffect::kSale ? discount(costRfMachine_[act.target]) : costRfMachine_[act.target];
            costRfMachine_[act.target] = (costRfMachine_[act.target] * 10);
        }
        else if (act.command == ECommand::kSell) {
            numMachine_[act.target] -= 1;
            costBuyMachine_[act.target] = (costBuyMachine_[act.target] * 5) / 6;
            wallet_ += (costBuyMachine_[act.target] + 3) / 4;
        }

        assert(wallet_ >= 0);
        ll fever = eff == EEffect::kFever ? 7 : 1;
        for (int i = 4 + (act.command == ECommand::kClick); i >= 0; --i) {
            wallet_ += efficiency((EMachine)i)*fever;
        }

        if (eff == EEffect::kBonus) {
            wallet_ += (wallet_ + 99) / 100;
        }
    }

    void dumplog() {
        clog << "money: " << wallet_ << '\n';
        clog << "nMachine" << numMachine_ << '\n';
        clog << "lMachine" << lvlMachine_ << '\n';
        clog << "buycost" << costBuyMachine_ << '\n';
        clog << "rfcost" << costRfMachine_ << '\n';
        clog << "efficiency:";
        repeat(i, 6) clog << efficiency(EMachine(i)) << " ";
        clog << '\n';
    }

};


//


namespace IN {
    const int maxTurnCount = 10000;
    EEffect effects[maxTurnCount];
    bool isGenerated = false;
}


//


void convertinput(const string& l) {

    using namespace IN;
    int fever = 0;
    int sale = 0;
    repeat(i, maxTurnCount) {
        auto e = charToEffect(l[i]);
        effects[i] = e == EEffect::kBonus ? EEffect::kBonus : EEffect::kNothing;
        if (fever > 0) {
            --fever;
            effects[i] = EEffect::kFever;
        }
        if (sale > 0) {
            --sale;
            effects[i] = EEffect::kSale;
        }
        if (e == EEffect::kFever) {
            fever = 20;
        }
        else if (e == EEffect::kSale) {
            sale = 1;
        }
    }
}


void generateInput() {
    using namespace IN;

    string l; l.reserve(maxTurnCount);
    int next = rand(0, 200);
    repeat(i, maxTurnCount) {
        if (next > 0) {
            --next;
            l.push_back('N');
        }
        else {
            l.push_back("DFS"[rand(0, 2)]);
            next = rand(100, 200);
        }
    }
    convertinput(l);
    isGenerated = true;
}


void scan() {
    using namespace IN;
    int n;
    scanner >> n;
    if (maxTurnCount != n) {
        generateInput();
        return;
    }
    string l;
    scanner >> l;

    convertinput(l);
}


//


namespace Solver {


    void renda(State& state, int currentTurnCount, bool echo = false) {
        int num = 0;
        repeat(m, 5) num += state.countOfMachine(EMachine(m));

        for (; currentTurnCount < IN::maxTurnCount - num; ++currentTurnCount) {
            state.applyAction(Action(ECommand::kClick), IN::effects[currentTurnCount]);
            if (echo) Action(ECommand::kClick).print();
        }
        for (; currentTurnCount < IN::maxTurnCount; ++currentTurnCount) {
            repeat(m, 5) {
                if (state.countOfMachine(EMachine(m)) > 0) {
                    state.applyAction(Action(ECommand::kSell, EMachine(m)), IN::effects[currentTurnCount]);
                    if (echo) Action(ECommand::kSell, EMachine(m)).print();
                    break;
                }
            }
        }
    }


    void solve() {

        State state;

        array<Action, IN::maxTurnCount> stackedActions;
        pair<ll, int> bestWalletTurn(0, 0);

        repeat(turncount, IN::maxTurnCount) {
            const EEffect effect = IN::effects[turncount];

            // Action action(ECommand::kClick);

            Tag<ll, Action> best(0, ECommand::kClick);

            auto topMachineI = 0;
            rrepeat(mm, 5) {
                if (state.countOfMachine((EMachine)mm) > 0) {
                    topMachineI = mm;
                    break;
                }
            }

            repeat(mm, 5) {
                EMachine m = (EMachine)mm;
                if (mm == topMachineI || mm == topMachineI + 1) {
                    if (state.buyableMachine(m, effect == EEffect::kSale)) {
                        chmax(best, Tag<ll, Action>(
                            state.oneMoreEfficiency(m) - state.efficiency(m),
                            Action(ECommand::kBuy, m)
                            ));
                    }
                }
                if (state.countOfMachine(m) > 0) {
                    if (state.reinforceableMachine(m, effect == EEffect::kSale)) {
                        chmax(best, Tag<ll, Action>(
                            state.nextLevelEfficiency(m) - state.efficiency(m),
                            Action(ECommand::kReinforce, m)
                            ));
                    }
                }
            }
            // rrepeat(mm, 4) {
            //     EMachine m = (EMachine)mm;
            //     if (state.countOfMachine(m) > 0 && mm < topMachineI-3) {
            //         chmax(best, Tag<ll, Action>(
            //             1e18,
            //             Action(ECommand::kSell, m)
            //             ));
            //     }
            // }

            if (state.reinforceableMachine(EMachine::kClicker, effect == EEffect::kSale)) {
                chmax(best, Tag<ll, Action>(
                    state.nextLevelEfficiency(EMachine::kClicker) - state.efficiency(EMachine::kClicker),
                    Action(ECommand::kReinforce, EMachine::kClicker)
                    ));
            }

            if (turncount > IN::maxTurnCount * 2 / 3 && best.second.command != ECommand::kClick) {
                State s = state;
                renda(s, turncount);
                chmax(bestWalletTurn, make_pair(s.wallet(), turncount));
            }

            // action.print();
            stackedActions[turncount] = best.second;
            state.applyAction(best.second, effect);
        }

        if (!IN::isGenerated) {
            state = State();
            repeat(i, bestWalletTurn.second) {
                state.applyAction(stackedActions[i], IN::effects[i]);
                stackedActions[i].print();
            }
            renda(state, bestWalletTurn.second, true);
            cout.flush();
        }
        else {
            clog << "## result" << endl;
            state = State();
            repeat(i, bestWalletTurn.second) {
                state.applyAction(stackedActions[i], IN::effects[i]);
                if (stackedActions[i].command != ECommand::kClick)
                    stackedActions[i].print();
            }
            clog << "-- before selling --" << endl;
            state.dumplog();
            renda(state, bestWalletTurn.second);
            clog << "-- final -- " << endl;
            state.dumplog();
            clog << "BEST:" << (double)bestWalletTurn.first << endl;
            clog << "bestWalletTurn: " << bestWalletTurn.second << endl;
        }
    }

}


int main() {
    using namespace IN;

    scan();

    Solver::solve();

    if (!isGenerated) {
        repeat(i, maxTurnCount) {
            string str;
            scanner >> str;
            assert(str == "ok");
        }
    }

    return 0;
}
0