Problem:
Score : 2000 points

Problem Statement

Given are integers N and K, and a prime number P. Find the number, modulo P, of directed graphs G with N vertices that satisfy below. Here, the vertices are distinguishable from each other.

G is a tournament, that is, G contains no duplicated edges or self-loops, and exactly one of the edges u\to v and v\to u exists for any two vertices u and v.

The in-degree of every vertex in G is at most K.

For any four distinct vertices a, b, c, and d in G, it is not the case that all of the six edges a\to b, b\to c, c\to a, a\to d, b\to d, and c\to d exist simultaneously.

Constraints

4 \leq N \leq 200

\frac{N-1}{2} \leq K \leq N-1

10^8<P<10^9

N and K are integers.

P is a prime number.

Input

Input is given from Standard Input in the following format:

N K P

Output

Print the number of directed graphs that satisfy the conditions, modulo P.

Sample Input 1

4 3 998244353

Sample Output 1

56

Among the 64 graphs with four vertices, 8 are isomorphic to the forbidden induced subgraphs, and the other 56 satisfy the conditions.

Sample Input 2

7 3 998244353

Sample Output 2

720

Sample Input 3

50 37 998244353

Sample Output 3

495799508

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

#include<bits/stdc++.h>
using namespace std;
const int N = 210;
int mod;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
/* math */
int n,_lim;
int binom[N][N],fac[N];

int dp[N][N];

inline int getmat(int k,int l,int lim){
	for(int i=1;i<=l;i++){
		for(int j=0;j<k;j++){
			if(i==1&&!j)dp[i][j]=1;
			else dp[i][j]=0;
			if(i)dp[i][j]=add(dp[i][j],dp[i-1][j]);
			if(j)dp[i][j]=add(dp[i][j],dp[i][j-1]);
			if(l-i+1+j-1>lim&&j)dp[i][j]=0;
		}
		for(int j=0;j<k;j++)if(k-j+i-1>lim)dp[i][j]=0;
//		for(int j=0;j<k;j++)cout << dp[i][j] << " ";
//		puts("");
	}
	int ans=0;
	for(int j=1;j<k;j++)ans=add(ans, dp[l][j]);
//	cerr << k << ":" << l << ":" << lim << ":" << ans << endl;
	return ans;
}

inline int solve(int lim,int n){
	if(n==1)return 0;
	if(n==0)return 1;
	if(lim<0)return 0;
	int ret=0;
	for(int k=1;k-1<=lim&&k<=n;k++){
		int tmp=mul(binom[n-1][k-1],mul(fac[n-k],fac[k-1]));
		ret=add(ret,mul(tmp, getmat(k,n-k,lim)));
	}
	return ret;
}

int main()
{
	cin >> n >> _lim >> mod;
	for(int i=0;i<=n;i++)for(int j=binom[i][0]=1;j<=i;j++)binom[i][j]=add(binom[i-1][j],binom[i-1][j-1]);
	for(int i=fac[0]=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
	int ans=0;
	for(int i=0;i<=_lim+1;i++){
		ans=add(ans, mul(mul(fac[i],binom[n][i]),solve(_lim-i, n-i)));
//		cout << ans << endl;
	}
	cout << ans << endl;
}