原题链接
\(该题运用到了杨表的知识 发该篇题解是为了加深对于杨表的理解\)
\(发表该篇题解仅用于个人理解 感觉洛谷上的题解更好\)
洛谷题解传送门
\(杨氏矩阵(Young tableau),又名杨表,是一种常用于表示论和舒伯特演算中的组合对象。\)
\(杨表是一种特殊的矩阵。它便于对称群和一般线性群的群表示和性质研究。\)
\(杨表由剑桥大学数学家阿尔弗雷德·杨(Alfred Young)于 1900 年首次提出,于 1903 年被德国数学家弗罗贝尼乌斯(Ferdinand Georg Frobenius)应用于对称群的研究。\)
\(杨表有一个基础的概念\)
\(对于1-n的元素填充 它的各行各列都得满足递增\)
\(臂长:对于每个单元格向右的元素个数(不包含自己)\)
\(腿长:对于每个单元格向下的元素个数(不包含自己)\)
\(勾长:对于每个单元格的臂长+腿长加一(即向右元素个数+向下元素个数+自己)\)
\(性质:\)
\(第一行的长度为该序列的LIS长度\)
\(第一列的长度为该序列的LDS长度\)
\(一个确定的序列可以生成两张杨表 一张记录其第一次插入的顺序 一张记录其形成的标准杨表\)
\(code:\)
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
#define pb push_back
#define pii pair<int,int>
using namespace std;
//const int mod=998244353;
int mod;
int gcd(int a,int b){return b?gcd(b,a%b):a;};
int qpw(int a,int b){int ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
int inv(int x){return qpw(x,mod-2);}
const int N=2e5+10;
int f[N],deg[N],siz[N];
vector<int>G[N];
int find(int x){
return f[x]==x?x:f[x]=find(f[x]);
}
void dfs1(int x,int fa){
for(int son:G[x]){
if(son==fa)continue;
dfs1(son,x);
if(deg[x]==2&°[son]==3){
siz[find(son)]++;
}else if(deg[son]==2&°[x]==3){
siz[find(x)]++;
}else if(deg[son]==3&°[x]==3){
siz[find(x)]+=siz[find(son)];
f[find(son)]=find(x);
}
}
}
void solve(){
int n,m;cin>>n>>m>>mod;
int ans=1;
for(int i=1;i<=n*m;i++)ans=ans*i%mod;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
ans=ans*inv(i+j-1)%mod;
}
}
map<vector<int>,int>dp;
vector<int>ve;
for(int i=1;i<=m;i++)ve.pb(0);
dp[ve]=1;
for(int k=1;k<=n*m;k++){
map<vector<int>,int>ndp;
for(auto x:dp){
auto v=x.first;
auto val=x.second;
for(int i=0;i<m;i++){
if(v[i]<n&&(i==0||v[i]<v[i-1])){
if(i!=m-1&&v[i]==n-1&&v[i+1]<n-1)continue;
++v[i];
ndp[v]=(ndp[v]+val)%mod;
--v[i];
}
}
}
swap(dp,ndp);
}
for(int i=0;i<m;i++)ve[i]=n;
ans=ans*dp[ve]%mod;
cout<<ans;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int _=1;
// cin>>_;
while(_--)solve();
}