题解:P16449 [XJTUPC 2026] 怪商一克拉七鲜鱼丸
这题真神了。妙得不得了。
好的先看两个操作的在干嘛。
交换一次操作可以把两个置换环合一起,或者将一个置换环分开。
小换的操作最小操作次数为
将一个数提前最多可以多一个前缀最大值。所以
小移的操作最小操作次数为
现在考虑计数
现在这里有个神必转换:
考虑在排列
具体地数列
有
最后得到的
显然的,满足
严格后缀最小值数就是前缀最大值数。
然后计数这两个东西是简单的。
具体地计
枚举放的数
可以对着
#include<bits/stdc++.h>
using namespace std;
long long dp[2][155][155][155];
long long ans[155][155];
int n,mod;
int main(){
cin>>n>>mod;
dp[0][n+1][0][0]=1;
bool T=0;
for(int i=n;i>=1;i--){
memset(dp[T^1],0,sizeof(dp[T^1]));
for(int j=1;j<=i+1;j++){
for(int k=0;k<=n-i;k++){
for(int l=0;l<=n-i;l++){
if(dp[T][j][k][l]==0)continue;
if(1<=min(i-1,j-1)){
dp[T^1][1][k+1][l]+=dp[T][j][k][l];
dp[T^1][min(i-1,j-1)+1][k+1][l]-=dp[T][j][k][l];
}
if(j<=i-1){
dp[T^1][j][k][l]+=(i-j)*dp[T][j][k][l]%mod;
dp[T^1][j+1][k][l]-=(i-j)*dp[T][j][k][l]%mod;
}
if(i<j)dp[T^1][i][k+1][l+1]+=dp[T][j][k][l];
else {dp[T^1][j][k][l+1]+=dp[T][j][k][l];dp[T^1][j+1][k][l+1]-=dp[T][j][k][l];}
}
}
}
T^=1;
for(int j=1;j<=i;j++){
for(int k=0;k<=n-i+1;k++){
for(int l=0;l<=n-i+1;l++){dp[T][j][k][l]=(dp[T][j][k][l]+dp[T][j-1][k][l])%mod;}//cout<<j<<" "<<k<<" "<<l<<" "<<dp[T][j][k][l]<<'\n';}
}
}
}
for(int k=1;k<=n;k++){
for(int l=1;l<=n;l++){
ans[n-k][n-l]=(dp[T][1][k][l]%mod+mod)%mod;
}
}
for(int k=0;k<n;k++){
for(int l=0;l<n;l++){
cout<<ans[k][l]<<" ";
}
cout<<'\n';
}
return 0;
}