#define NDEBUG #include <cassert> #include <cctype> #include <iostream> #include <limits> #include <unistd.h> #include <vector> using namespace std; typedef long long LL; typedef signed char int8; class Input { public: Input() { bufpos = bufend = buffer; eof = false; } bool Eof() { return eof; } char Peek() { if(bufpos == bufend) Grab(); return *bufpos; } unsigned char UPeek() { return static_cast<unsigned char>(Peek()); } void SkipWS(); template<class T> T Get(); void operator()() {} template<class Arg, class... Args> void operator()(Arg &arg, Args &... args) { arg = Get<Arg>(); operator()(args...); } private: static const int BUFSIZE = 1<<16; char buffer[BUFSIZE]; char *bufpos; char *bufend; bool eof; void Grab(); }; void Input::Grab() { if(eof) return; bufpos = buffer; bufend = buffer + read(0, buffer, BUFSIZE); if(bufend==bufpos) { eof=true; *bufpos=0; } } template<> inline char Input::Get<char>() { char res = Peek(); ++bufpos; return res; } void Input::SkipWS() { while(isspace(UPeek())) Get<char>(); } template<> unsigned Input::Get<unsigned>() { SkipWS(); unsigned x = 0; while(isdigit(UPeek())) { x = 10u * x + (Get<char>()-'0'); } return x; } template<> int Input::Get<int>() { SkipWS(); bool neg = false; if(Peek()=='-') { neg=true; Get<char>(); } unsigned x = Get<unsigned>(); if (neg) x = -x; return static_cast<int>(x); } Input IN; // ------------------ int numPlayers, winCycleLen; vector<int> initialMoney; vector<int8> winCycle; void ReadInput() { IN(numPlayers); initialMoney.resize(numPlayers); for (int &m : initialMoney) IN(m); IN(winCycleLen); winCycle.resize(winCycleLen); IN.SkipWS(); for (int8 &win : winCycle) { char c; IN(c); assert(c=='W' || c=='P'); win = (c=='W') ? +1 : -1; } } int Gcd(int a, int b) { return b==0 ? a : Gcd(b, a%b); } long long SolveCycle(const int start, const int subcycleLen, const int stepBack, vector<int> &firstSeen) { firstSeen.assign(4 * subcycleLen + 1, -1); const int endCash = 2 * subcycleLen; int t = 2 * subcycleLen; int idx = start; int cash = endCash; int minSeen = cash; firstSeen[cash] = t; int lostPerCycle = 0; long long res = numeric_limits<long long>::max(); while (t > 0) { --t; idx = (idx + stepBack) % winCycleLen; cash -= winCycle[idx]; if (cash < minSeen) minSeen = cash; firstSeen[cash] = t; if (t == subcycleLen) { assert(idx == start); lostPerCycle = cash - endCash; } else if (t < subcycleLen) { for (int player = idx; player < numPlayers; player += winCycleLen) { int want = cash - initialMoney[player]; long long tZero; if (want >= minSeen) { tZero = firstSeen[want] - t; } else if (lostPerCycle > 0) { const int fullCycles = (minSeen - want + lostPerCycle - 1) / lostPerCycle; int wantLater = want + fullCycles * lostPerCycle; assert(wantLater >= minSeen && wantLater <= cash); tZero = firstSeen[wantLater] - t + LL(subcycleLen) * fullCycles; } else { continue; } res = min(res, player + 1 + (tZero-1) * numPlayers); } } } return res; } long long Solve() { long long res = numeric_limits<long long>::max(); int g = Gcd(numPlayers, winCycleLen); vector<int> helper; int stepBack = (winCycleLen - numPlayers % winCycleLen) % winCycleLen; for (int start = 0; start < g; ++start) { res = min(res, SolveCycle(start, winCycleLen / g, stepBack, helper)); } return res; } int main() { ReadInput(); long long res = Solve(); if (res == numeric_limits<long long>::max()) { res = -1; } cout << res << '\n'; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | #define NDEBUG #include <cassert> #include <cctype> #include <iostream> #include <limits> #include <unistd.h> #include <vector> using namespace std; typedef long long LL; typedef signed char int8; class Input { public: Input() { bufpos = bufend = buffer; eof = false; } bool Eof() { return eof; } char Peek() { if(bufpos == bufend) Grab(); return *bufpos; } unsigned char UPeek() { return static_cast<unsigned char>(Peek()); } void SkipWS(); template<class T> T Get(); void operator()() {} template<class Arg, class... Args> void operator()(Arg &arg, Args &... args) { arg = Get<Arg>(); operator()(args...); } private: static const int BUFSIZE = 1<<16; char buffer[BUFSIZE]; char *bufpos; char *bufend; bool eof; void Grab(); }; void Input::Grab() { if(eof) return; bufpos = buffer; bufend = buffer + read(0, buffer, BUFSIZE); if(bufend==bufpos) { eof=true; *bufpos=0; } } template<> inline char Input::Get<char>() { char res = Peek(); ++bufpos; return res; } void Input::SkipWS() { while(isspace(UPeek())) Get<char>(); } template<> unsigned Input::Get<unsigned>() { SkipWS(); unsigned x = 0; while(isdigit(UPeek())) { x = 10u * x + (Get<char>()-'0'); } return x; } template<> int Input::Get<int>() { SkipWS(); bool neg = false; if(Peek()=='-') { neg=true; Get<char>(); } unsigned x = Get<unsigned>(); if (neg) x = -x; return static_cast<int>(x); } Input IN; // ------------------ int numPlayers, winCycleLen; vector<int> initialMoney; vector<int8> winCycle; void ReadInput() { IN(numPlayers); initialMoney.resize(numPlayers); for (int &m : initialMoney) IN(m); IN(winCycleLen); winCycle.resize(winCycleLen); IN.SkipWS(); for (int8 &win : winCycle) { char c; IN(c); assert(c=='W' || c=='P'); win = (c=='W') ? +1 : -1; } } int Gcd(int a, int b) { return b==0 ? a : Gcd(b, a%b); } long long SolveCycle(const int start, const int subcycleLen, const int stepBack, vector<int> &firstSeen) { firstSeen.assign(4 * subcycleLen + 1, -1); const int endCash = 2 * subcycleLen; int t = 2 * subcycleLen; int idx = start; int cash = endCash; int minSeen = cash; firstSeen[cash] = t; int lostPerCycle = 0; long long res = numeric_limits<long long>::max(); while (t > 0) { --t; idx = (idx + stepBack) % winCycleLen; cash -= winCycle[idx]; if (cash < minSeen) minSeen = cash; firstSeen[cash] = t; if (t == subcycleLen) { assert(idx == start); lostPerCycle = cash - endCash; } else if (t < subcycleLen) { for (int player = idx; player < numPlayers; player += winCycleLen) { int want = cash - initialMoney[player]; long long tZero; if (want >= minSeen) { tZero = firstSeen[want] - t; } else if (lostPerCycle > 0) { const int fullCycles = (minSeen - want + lostPerCycle - 1) / lostPerCycle; int wantLater = want + fullCycles * lostPerCycle; assert(wantLater >= minSeen && wantLater <= cash); tZero = firstSeen[wantLater] - t + LL(subcycleLen) * fullCycles; } else { continue; } res = min(res, player + 1 + (tZero-1) * numPlayers); } } } return res; } long long Solve() { long long res = numeric_limits<long long>::max(); int g = Gcd(numPlayers, winCycleLen); vector<int> helper; int stepBack = (winCycleLen - numPlayers % winCycleLen) % winCycleLen; for (int start = 0; start < g; ++start) { res = min(res, SolveCycle(start, winCycleLen / g, stepBack, helper)); } return res; } int main() { ReadInput(); long long res = Solve(); if (res == numeric_limits<long long>::max()) { res = -1; } cout << res << '\n'; } |