#include using namespace std ; #define ft first #define sd second #define pb push_back #define all(x) x.begin(),x.end() #define ll long long int #define vi vector #define vii vector > #define pii pair #define vl vector #define vll vector > #define pll pair #define mp make_pair #define sc1(x) scanf("%d",&x) #define sc2(x,y) scanf("%d%d",&x,&y) #define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define scll1(x) scanf("%lld",&x) #define scll2(x,y) scanf("%lld%lld",&x,&y) #define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z) #define pr1(x) printf("%d\n",x) #define pr2(x,y) printf("%d %d\n",x,y) #define pr3(x,y,z) printf("%d %d %d\n",x,y,z) #define prll1(x) printf("%lld\n",x) #define prll2(x,y) printf("%lld %lld\n",x,y) #define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z) #define pr_vec(v) for(int i=0;i #include using namespace __gnu_pbds; const int maxn = 111; const int maxm = 11111; int mod, n, c; int dp[111][111], nCr[111][111], P[11111]; // this function calculates F(i, j) = i! / (j! * (i - j)!) % mod void Combinations() { for(int i=0; i<=n; i++) { for(int j=0; j<=i; j++) { nCr[i][j] = 0; } } for(int i=0; i<=n; i++) { nCr[i][0] = 1; } for(int i=1; i<=n; i++) { for(int j=1; j<=i; j++) { nCr[i][j] = nCr[i-1][j-1] + nCr[i-1][j]; if( nCr[i][j] >= mod ) { nCr[i][j] -= mod; } } } } void solve() { cin >> n >> c >> mod; assert( n <= 100 && n >= 1 ); assert( c >= 1 && c <= n ); assert( mod >= 1 && mod <= 1e9 ); Combinations(); P[0] = 1; // ith entry contains 2^i % mod for(int i=1; i= mod ) { P[i] -= mod; } } // resetting dp for(int i=0; i<=n; i++) { for(int j=0; j<=i; j++) { dp[i][j] = 0; } } // we will add nodes one by one to our graph G. // here, i denotes the node that we are currently adding adding to our graph G // assuming that we have already added previous i-1 nodes to the graph. // dp[i][j] will denotes the number of ways of removing subset of edges from the // given graph such that the resulting graph will have exactly j components. for(int i=1; i<=n; i++) { int sum = 0; // j denotes the number of components we want to have in the resulting graph. // It should also be noted that complete graph consisting of i nodes will have // i * (i-1) / 2 edges and removal of any edge subset will result into decomposition // of graph G into 1 or more component ( maximum i components ) // we will be calculating answers when G will decompose into 2, 3, 4 and so on upto // i components and then will subtract all these answer from total possible sets of edges i.e // 2^(i*(i-1)/2) to get the answer for exactly 1 component. // notice that when we partition the complete graph consisting of i nodes then // ith node has to be in some component and lets k denotes the size of that component. for(int j=i; j>=2; j--) { for(int k=1; k<=i-1; k++) { // we have the size of component containing ith node = k, as we already have ith node // in this component we will be choosing k-1 nodes from the left i-1 nodes and multiplying // it with the number of ways of making 1 component with k vertices and j-1 component with i-k // so that we can have j components in total. dp[i][j] += ( 1LL * ( 1LL * nCr[i-1][k-1] * dp[k][1] % mod ) * dp[i-k][j-1] ) % mod; if( dp[i][j] >= mod ) dp[i][j] -= mod; } sum += dp[i][j]; if( sum >= mod ) sum -= mod; } // finding the number of ways of making 1 component from i nodes by subtracting answer for 2, 3, 4, .. i components // from the total answer. dp[i][1] = P[ i * (i-1) / 2 ] - sum; if( dp[i][1] < 0 ) dp[i][1] += mod; } int ans = dp[n][c]; if( c == 1 ) { ans --; // this is done to remove the empty subset of edges considered. if( ans < 0 ) ans += mod; } cout << ans << "\n"; } int main() { // f_in( "in16.txt" ); // f_out( "out16.txt" ); int t; cin >> t; assert( t <= 50 && t >= 1 ); while( t-- ) solve(); return 0; }