Cod sursa(job #2060307)

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

constexpr auto MODMAX = 98999;
constexpr auto MAXM = 201;
namespace std
{
// C++14 features drop-in replacement kindly stolen from https://stackoverflow.com/a/20101039
template< std::size_t ... i >
struct index_sequence
{
    typedef std::size_t value_type;

    typedef index_sequence<i...> type;

    // gcc-4.4.7 doesn't support `constexpr` and `noexcept`.
    static /*constexpr*/ std::size_t size() /*noexcept*/
    { 
        return sizeof ... (i); 
    }
};


// this structure doubles index_sequence elements.
// s- is number of template arguments in IS.
template< std::size_t s, typename IS >
struct doubled_index_sequence;

template< std::size_t s, std::size_t ... i >
struct doubled_index_sequence< s, index_sequence<i... > >
{
    typedef index_sequence<i..., (s + i)... > type;
};

// this structure incremented by one index_sequence, iff NEED-is true, 
// otherwise returns IS
template< bool NEED, typename IS >
struct inc_index_sequence;

template< typename IS >
struct inc_index_sequence<false,IS>{ typedef IS type; };

template< std::size_t ... i >
struct inc_index_sequence< true, index_sequence<i...> >
{
    typedef index_sequence<i..., sizeof...(i)> type;
};



// helper structure for make_index_sequence.
template< std::size_t N >
struct make_index_sequence_impl : 
           inc_index_sequence< (N % 2 != 0), 
                typename doubled_index_sequence< N / 2,
                           typename make_index_sequence_impl< N / 2> ::type
               >::type
       >
{};

 // helper structure needs specialization only with 0 element.
template<>struct make_index_sequence_impl<0>{ typedef index_sequence<> type; };



// OUR make_index_sequence,  gcc-4.4.7 doesn't support `using`, 
// so we use struct instead of it.
template< std::size_t N >
struct make_index_sequence : make_index_sequence_impl<N>::type {};

//index_sequence_for  any variadic templates
template< typename ... T >
struct index_sequence_for : make_index_sequence< sizeof...(T) >{};

}

//end replacement

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;
}