ADDED SRM/548-U/1A.cpp Index: SRM/548-U/1A.cpp ================================================================== --- SRM/548-U/1A.cpp +++ SRM/548-U/1A.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex CMP; + +class KingdomAndTrees { public: + int minLevel(vector heights) + { + // (L,R] + int L = -1; + int R = 1000000000; + while(R-L>1) + { + int C = (L+R)/2; + (possible(C,heights) ? R : L) = C; + } + return R; + } + + bool possible(int C, const vector& h) + { + int last = max(1, h[0]-C); + for(int i=1; i +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template ostream& operator<<(ostream& os, const vector& v) + { os << "{ "; + for(typename vector::const_iterator it=v.begin(); it!=v.end(); ++it) + os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } +void verify_case(const int& Expected, const int& Received) { + bool ok = (Expected == Received); + if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; + cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } +#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); +#define END verify_case(_, KingdomAndTrees().minLevel(heights));} +int main(){ + +CASE(0) + int heights_[] = {9, 5, 11}; + vector heights(heights_, heights_+sizeof(heights_)/sizeof(*heights_)); + int _ = 3; +END +CASE(1) + int heights_[] = {5, 8}; + vector heights(heights_, heights_+sizeof(heights_)/sizeof(*heights_)); + int _ = 0; +END +CASE(2) + int heights_[] = {1, 1, 1, 1, 1}; + vector heights(heights_, heights_+sizeof(heights_)/sizeof(*heights_)); + int _ = 4; +END +CASE(3) + int heights_[] = {548, 47, 58, 250, 2012}; + vector heights(heights_, heights_+sizeof(heights_)/sizeof(*heights_)); + int _ = 251; +END +CASE(4) + int heights_[] = {337994619,837714986,7014426,516695490,268514071,590654553,940024470,79308071,891444369,231310251,172567010,283491054,951215936,92716118,911004789,896372476,617116292,874491895,120052194,635772188,938392572,466867891,418351197,278475278,635224368,38779964,762367612,370214557,20108108,314281202,644947239,868648377,617056931,542328796,280916141,281585869,895175595,529854516,862330692,733665485,173060292,579136324,401396401,303236137,161627936,410922706,172892990,840336279,848958999,849348801}; + vector heights(heights_, heights_+sizeof(heights_)/sizeof(*heights_)); + int _ = -1; +END +CASE(5) + int heights_[] = {1000000000,1}; + vector heights(heights_, heights_+sizeof(heights_)/sizeof(*heights_)); + int _ = 500000000; +END + +} +// END CUT HERE ADDED SRM/548-U/1B.cpp Index: SRM/548-U/1B.cpp ================================================================== --- SRM/548-U/1B.cpp +++ SRM/548-U/1B.cpp @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex CMP; + +template +struct DP3 +{ + int N1, N2, N3; + vector data; + DP3(int N1, int N2, int N3, const T& t = T()) + : N1(N1), N2(N2), N3(N3), data(N1*N2*N3, t) { assert(data.size()*sizeof(T)<(1<<26)); } + T& operator()(int i1, int i2, int i3) + { return data[ ((i1*N2)+i2)*N3+i3 ]; } + void swap(DP3& rhs) + { data.swap(rhs.data); } +}; + +struct cmp { + int N; + cmp(int N):N(N){} + bool operator()(int a, int b) const + { + if( abs(2*a - N*N) != abs(2*b - N*N) ) + return abs(2*a - N*N) < abs(2*b - N*N); + return a < b; + } +}; +class KingdomAndDice { public: + double newFairness(vector firstDie, vector secondDie, int X) + { + int N = firstDie.size(); + sort(secondDie.begin(), secondDie.end()); + + vector choice; + { + choice.push_back(N); + for(int i=0; i+1& choice, int K) + { + DP3 dp(N+1, K+1, N*N+1); + for(int i=0; i<=N; ++i) + for(int p=0; p<=K; ++p) + for(int sum=0; sum<=N*N; ++sum) + { + if(i==0) + { + dp(i,p,sum) = (sum==base && p<=choice[i]); + } + else + { + bool b = false; + for(int z=0; z<=p && z<=choice[i]; ++z) + if(sum>=i*z) + b = b | dp(i-1,p-z,sum-i*z); + dp(i,p,sum) = b; + } + } + + vector cand; + for(int sum=0; sum<=N*N; ++sum) + if( dp(N,K,sum) ) + cand.push_back( sum ); + return *min_element(cand.begin(), cand.end(), cmp(N)) / double(N*N); + } +}; + +// BEGIN CUT HERE +#include +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template ostream& operator<<(ostream& os, const vector& v) + { os << "{ "; + for(typename vector::const_iterator it=v.begin(); it!=v.end(); ++it) + os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } +void verify_case(const double& Expected, const double& Received) { + bool ok = (abs(Expected - Received) < 1e-9); + if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; + cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } +#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); +#define END verify_case(_, KingdomAndDice().newFairness(firstDie, secondDie, X));} +int main(){ + +CASE(0) + int firstDie_[] = {0, 2, 7, 0}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {6, 3, 8, 10}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 12; + double _ = 0.4375; +END +CASE(1) + int firstDie_[] = {0, 2, 7, 0}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {6, 3, 8, 10}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 10; + double _ = 0.375; +END +CASE(2) + int firstDie_[] = {0, 0}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {5, 8}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 47; + double _ = 0.5; +END +CASE(3) + int firstDie_[] = {19, 50, 4}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {26, 100, 37}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 1000; + double _ = 0.2222222222222222; +END +CASE(4) + int firstDie_[] = {6371, 0, 6256, 1852, 0, 0, 6317, 3004, 5218, 9012}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {1557, 6318, 1560, 4519, 2012, 6316, 6315, 1559, 8215, 1561}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 10000; + double _ = 0.49; +END +CASE(5) + int firstDie_[] = {278130165,933636493,607327308,19369203,439158229,445295066,370731340,551180273,163280323,359800317,834663837,108871632,362106962,921853660,145507840,284869553,246938492,379648759,956330140,525562675,251028940,270135098,862786589,513909283,412651940,499422899,724171306,922270222,938213346,61418124,248820926,891527589,812074952,155495258,23280465,761818758,328244247,975585791,108105856,414583437,424242761,168720992,585728188,0,0,0,0,0,0,0}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {475017760,773630717,985005264,963668637,320647204,665487259,585555327,272107932,203172682,57845645,311126817,496577583,834654861,77335024,405827438,231342594,943378345,971851607,455697802,119475931,551079372,838525393,192593102,990828850,382044077,590561977,229071016,962163538,621629435,727621063,109926457,152882146,9199017,615779540,160320904,216276208,675743894,414050471,126645085,238141513,151262148,280509327,923103663,125699296,790073355,738597671,864455279,384833125,510401421,219630179}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 1000000000; + double _ = 0.5; +END +CASE(6) + int firstDie_[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {475017760,773630717,985005264,963668637,320647204,665487259,585555327,272107932,203172682,57845645,311126817,496577583,834654861,77335024,405827438,231342594,943378345,971851607,455697802,119475931,551079372,838525393,192593102,990828850,382044077,590561977,229071016,962163538,621629435,727621063,109926457,152882146,9199017,615779540,160320904,216276208,675743894,414050471,126645085,238141513,151262148,280509327,923103663,125699296,790073355,738597671,864455279,384833125,510401421,219630179}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 1000000000; + double _ = 0.5; +END +CASE(6) + int firstDie_[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {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}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 100; + double _ = 0.5; +END +CASE(7) +int firstDie_[] = {0,0}; + vector firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); + int secondDie_[] = {1,2}; + vector secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); + int X = 4; + double _ = 1; +END + +} +// END CUT HERE