Cod sursa(job #2060305)

Utilizator andreioneaAndrei Onea andreionea Data 8 noiembrie 2017 06:19:20
Problema Numerele lui Stirling Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.12 kb
#include <fstream>
#include <type_traits>
#include <array>
#include <utility>

constexpr auto MODMAX = 98999;
constexpr auto MAXM = 201;

struct StirlingCase1{};
struct StirlingCase2{};
struct StirlingRegularCase{};

template<class Case, int N, int M>
struct Stirling1Impl{};

template<int X>
struct Stirling1;

template<class Case, int N, int M>
struct Stirling2Impl{};

template<int X>
struct Stirling2;

template<int N, int M>
struct ComputeCase
{
	using type = typename std::conditional<(N==0 && M == 0), StirlingCase1,
		typename std::conditional<(N == 0 || M == 0), StirlingCase2, StirlingRegularCase>::type >::type;
};

template<int N, int M>
struct Stirling1Impl<StirlingCase1, N, M>
{
	static constexpr int value = 1;
};

template<int N, int M>
struct Stirling1Impl<StirlingCase2, N, M>
{
	static constexpr int value = 0;
};

template<int N, int M>
struct Stirling1Impl<StirlingRegularCase, N, M>
{
	using first = typename ComputeCase<N-1, M>::type;
	using second = typename ComputeCase<N-1, M-1>::type;
	static constexpr int value = (-(N - 1) * Stirling1Impl<first, N - 1, M>::value + Stirling1Impl<second, N - 1, M - 1>::value) % MODMAX;
};

template<int X>
struct Stirling1
{
	using StirlingCase = typename ComputeCase<X / MAXM, X % MAXM>::type;
	static constexpr int value = Stirling1Impl<StirlingCase, X / MAXM, X % MAXM>::value;
};

template< size_t ... I >
static constexpr std::array< int, sizeof...(I) >  buildStirling1( std::index_sequence<I...> seq ) 
{ 
   return std::array<int, sizeof...(I) > { Stirling1<I>::value... };
}

template <int MAXIMUMN, int MAXIMUMM>
struct AllStirling1
{
	static constexpr auto value = buildStirling1(std::make_index_sequence<MAXIMUMN*MAXM + MAXIMUMM>{});
};


//------------
template<int N, int M>
struct Stirling2Impl<StirlingCase1, N, M>
{
	static constexpr int value = 1;
};

template<int N, int M>
struct Stirling2Impl<StirlingCase2, N, M>
{
	static constexpr int value = 0;
};

template<int N, int M>
struct Stirling2Impl<StirlingRegularCase, N, M>
{
	using first = typename ComputeCase<N-1, M>::type;
	using second = typename ComputeCase<N-1, M-1>::type;
	static constexpr int value = (M * Stirling2Impl<first, N - 1, M>::value + Stirling2Impl<second, N - 1, M - 1>::value) % MODMAX;
};

template<int X>
struct Stirling2
{
	using StirlingCase = typename ComputeCase<X / MAXM, X % MAXM>::type;
	static constexpr int value = Stirling2Impl<StirlingCase, X / MAXM, X % MAXM>::value;
};

template< size_t ... I >
static constexpr std::array< int, sizeof...(I) >  buildStirling2( std::index_sequence<I...> seq ) 
{ 
   return std::array<int, sizeof...(I) > { Stirling2<I>::value... };
}

template <int MAXIMUMN, int MAXIMUMM>
struct AllStirling2
{
	static constexpr auto value = buildStirling2(std::make_index_sequence<MAXIMUMN*MAXM + MAXIMUMM>{});
};

int main()
{
	constexpr auto s1 = AllStirling1<200, 200>::value;
	constexpr auto s2 = AllStirling2<200, 200>::value;
	std::ifstream f("stirling.in");
	std::ofstream g("stirling.out");
	int T;
	f >> T;
	while (T--) {
		int x,n,m;
		f >> x >> n >> m;
		if (x == 1) {
			g << s1[n * MAXM + m];
		}
		else {
			g << s2[n * MAXM + m];	
		}
		g << "\n";
	}
	f.close();
	g.close();
	return 0;
}