250pt:
對普通nim遊戲的改編,取石子的時候只能從前往後取,每次取非空的石子,不能取者為輸。
我是從後往前推的,注意當前數字如果>1,不管後面是必勝態還是必敗態,肯定能調節成必勝態,如果=1,就身不由己了。。
500pt
一開始,你有n個工廠,k個專家,每工作一輪,能獲得n*k的gold,購買一個工廠或者一個專家需要price的gold,你想要獲得的gold是target,當你具備足夠的錢買一個專家或者工廠的時候,你可以買任意多個專家或工廠。問你最小需要幾輪才能獲得target的gold。
這是一個 看似難寫,實則更難寫的類比題。。
注意到n k肯定是越接近越好,還有當前如果要買一個專家或者工廠,那肯定是花所有的錢去買(n,k肯定是越早增大越好)。因為下一輪就賺回來了。還有就是假設當前的錢>=price了,就需要先判斷一下是不是要買工廠或者專家了,因為有可能憑藉當前的nk,很快就能到達target了。
代碼寫的比較渣,錯了很多遍
#include <cstdio>#include <cstring>#include <cctype>#include <cstdlib>#include <cmath>#include <ctime>#include <iostream>#include <map>#include <set>#include <list>#include <sstream>#include <queue>#include <deque>#include <stack>#include <vector>#include <bitset>#include <algorithm>using namespace std;typedef long long lld;class StrongEconomy {public: lld ABS(lld a) { if(a > 0) return a; return -a; } void get(lld &n,lld &k,lld &tim) { if(tim >= ABS(n-k) ) { lld tn = n , tk = k; n = (tn+tk+tim) / 2; k = (tn+tk+tim+1) / 2; } else { if(n>k) k+=tim; else n+=tim; } } lld gao(lld n,lld k,lld price,lld target,lld earn) { lld tim = earn / price; earn -= tim * price; get(n,k,tim); lld tmp = mul(n,k); if(tmp == -1) return tmp; lld ans = (target - earn)/tmp; if((target-earn)%tmp) ans ++; return ans; } lld mul(lld a,lld b) { lld ans = 0; bool flag = false; for(int i=0; i<50; i++) { // cout<<ans<<endl; if(b&(1LL<<i)) { if(flag) return -1; ans = ans + a; if(ans > 1000000000000LL) return -1; } a = a + a; if(a > 1000000000000LL) flag = true; } return ans; } lld earn(lld n, lld k, lld price, lld target) { if(mul(n,k) == -1) return 1; lld round = 0; lld earn = 0; while(true) { lld tmp = mul(n,k); if(tmp == -1) return round ; // cout<<earn<<endl; if(earn >= target) break; if(earn >= price) { lld tmp = mul(n,k); lld tmp1 = (target - earn) / tmp ; if((target-earn)%tmp) tmp1++; lld tmp2 = gao(n,k,price,target,earn); // cout<<tmp1<<" "<<tmp2<<endl; if(tmp1 < tmp2 ) { round += tmp1; break; } else { lld tim = earn / price; if(tmp2 == -1) return round + 1; earn -= tim * price; // cout<<"pre"<<" "<<n<<" "<<k<<" "<<tim<<endl; get(n,k,tim); // cout<<n<<" "<<k<<" "<<earn<<endl; } } else if(price < target){ lld tmp = n * k; lld t = (price-earn)/tmp; if((price-earn)%tmp) t++; round += t; earn += t * n * k; cout<<"earn"<<" "<<earn<<endl; } else { lld tmp = n * k; lld t = (target-earn)/tmp; if((target-earn)%tmp) t++; round += t; earn += t * n * k; } // cout<<n<<" "<<k<<endl; } return round; }// BEGIN CUT HEREpublic: void run_test(int Case) { if ((Case == -1) || (Case == 1)) test_case_1(); }private: template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); } void verify_case(int Case, const lld &Expected, const lld &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } } //void test_case_0() { lld Arg0 = 4294967297LL; lld Arg1 = 4294967297LL; lld Arg2 = 1000000000000LL; lld Arg3 = 100000000000LL; lld Arg4 = 1LL; verify_case(0, Arg4, earn(Arg0, Arg1, Arg2, Arg3)); } void test_case_1() { lld Arg0 = 3LL; lld Arg1 = 2LL; lld Arg2 = 1000000000000LL; lld Arg3 = 222LL; lld Arg4 = 37LL; verify_case(1, Arg4, earn(Arg0, Arg1, Arg2, Arg3)); }//void test_case_2() { lld Arg0 = 1LL; lld Arg1 = 1LL; lld Arg2 = 500000LL; lld Arg3 = 1000002LL; lld Arg4 = 1000001LL; verify_case(2, Arg4, earn(Arg0, Arg1, Arg2, Arg3)); } //void test_case_3() { lld Arg0 = 5LL; lld Arg1 = 4LL; lld Arg2 = 15LL; lld Arg3 = 100LL; lld Arg4 = 5LL; verify_case(3, Arg4, earn(Arg0, Arg1, Arg2, Arg3)); }// END CUT HERE};// BEGIN CUT HEREint main() { StrongEconomy ___test; ___test.run_test(-1);}// END CUT HERE