Artifact Content
Not logged in

Artifact 3c1fd7f25faac951bd82156600e49ffcf1999843


#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <functional>
#include <complex>
#include <queue>
#include <stack>
#include <cmath>
#include <cassert>
using namespace std;
typedef long long LL;
typedef long double LD;
typedef complex<LD> CMP;

template<typename T>
struct DP3
{
	int N1, N2, N3;
	vector<T> 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 <int> firstDie, vector <int> secondDie, int X)
	{
		int N = firstDie.size();
		sort(secondDie.begin(), secondDie.end());

		vector<int> choice;
		{
			choice.push_back(N);
			for(int i=0; i+1<N; ++i)
				choice.push_back(secondDie[i+1]-secondDie[i]-1);
			choice.push_back(X-secondDie.back());
		}
		int base = 0;
		{
			for(int k=0; k<N; ++k)
				if( firstDie[k]!=0 && firstDie[k]<secondDie[0] ) {
					choice[0] --;
					base += 0;
				}
			for(int i=0; i+1<N; ++i)
				for(int k=0; k<N; ++k)
					if( firstDie[k]!=0 && secondDie[i]<firstDie[k] && firstDie[k]<secondDie[i+1] ) {
						choice[i+1] --;
						base += i+1;
					}
			for(int k=0; k<N; ++k)
				if( firstDie[k]!=0 && secondDie[N-1]<firstDie[k] ) {
					choice[N] --;
					base += N;
				}
		}
		return solve(N, base, choice, count(firstDie.begin(), firstDie.end(), 0));
	}

	double solve(int N, int base, const vector<int>& choice, int K)
	{
		DP3<int> 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<int> 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 <ctime>
double start_time; string timer()
 { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& v)
 { os << "{ ";
   for(typename vector<T>::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 <int> firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); 
	int secondDie_[] = {6, 3, 8, 10};
	  vector <int> secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); 
	int X = 12; 
	double _ = 0.4375; 
END
CASE(1)
	int firstDie_[] = {0, 2, 7, 0};
	  vector <int> firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); 
	int secondDie_[] = {6, 3, 8, 10};
	  vector <int> secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); 
	int X = 10; 
	double _ = 0.375; 
END
CASE(2)
	int firstDie_[] = {0, 0};
	  vector <int> firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); 
	int secondDie_[] = {5, 8};
	  vector <int> secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); 
	int X = 47; 
	double _ = 0.5; 
END
CASE(3)
	int firstDie_[] = {19, 50, 4};
	  vector <int> firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); 
	int secondDie_[] = {26, 100, 37};
	  vector <int> 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 <int> firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); 
	int secondDie_[] = {1557, 6318, 1560, 4519, 2012, 6316, 6315, 1559, 8215, 1561};
	  vector <int> 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 <int> 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 <int> 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 <int> 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 <int> 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 <int> 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 <int> secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); 
	int X = 100;
	double _ = 0.5; 
END
CASE(7)
int firstDie_[] = {0,0};
	  vector <int> firstDie(firstDie_, firstDie_+sizeof(firstDie_)/sizeof(*firstDie_)); 
	  int secondDie_[] = {1,2};
	  vector <int> secondDie(secondDie_, secondDie_+sizeof(secondDie_)/sizeof(*secondDie_)); 
	int X = 4; 
	double _ = 1; 
END

}
// END CUT HERE