题解:AT_agc060_c [AGC060C] Large Heap
one_last_kiss · · 题解
思路
题面要求排列需要满足“堆”的性质,那我们不妨直接把它看成一个满足小根堆性质的满二叉树。
::::info[前置]{open} 如何求满足小根堆性质的满二叉树的个数呢?
排列的总个数为
那么总方案为
容易观察
令
首先排除不合法的情况,即
接着考虑转移:
1.左链移动到
2.右链移动到
然后就做完了。
#include<bits/stdc++.h>
#define int long long
#define PII pair<int,int>
#define INF 1e12
#define cc cin
#define oo cout
#define nm tie(0)
using namespace std;
const int mod=998244353;
int qpow(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 n,a,b;
int p[5005];
int dp[5005][5005];
signed main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cc.nm;
oo.nm;
cin>>n>>a>>b;
a++,b++;
p[0]=1;
for(int i=1;i<=n;i++) p[i]=p[i-1]*2%mod;
dp[1][1]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i<a&&j>=b) continue;
dp[i+1][j]+=(dp[i][j]*(p[n-i]-1)%mod*qpow(p[n-i]+p[n-j]-2,mod-2)%mod);
dp[i+1][j]%=mod;
dp[i][j+1]+=(dp[i][j]*(p[n-j]-1)%mod*qpow(p[n-i]+p[n-j]-2,mod-2)%mod);
dp[i][j+1]%=mod;
}
}
cout<<dp[n][n]<<"\n";
return 0;
}
/*
*/