TopCoder 14084 BearPermutations2【笛卡尔树+dp】
2024-08-30 07:49:20
传送:https://vjudge.net/problem/TopCoder-14084
只是利用了笛卡尔树的性质,设f[i][j]为区间[i,j]的贡献,然后枚举中间最大的点k来转移,首先是两侧小区间贡献的,f[i][k-1]*fac[j-k]+f[k+1][j]*fac[k-i],大概是方案数相乘的形式
然后考虑中间点的儿子的贡献,是\( fac[k-i-1]|*fac[j-k-1]|*sum_{l=i}{k-1}\sum_{r=k+1}{j}r-l \),前面表示两侧任意排列,后面两个求和可以化简
然后最后整体乘c[j-i][k-i]表示选出一部分作为左儿子
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
class BearPermutations2
{
private:
long long mod,f[105][105],c[105][105],fac[105];
public:
long long clc(long long l,long long r)
{
return (l+r)*(r-l+1)/2%mod;
}
int getSum(int n,int MOD)
{
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
mod=MOD;
fac[0]=1;
for(int i=1;i<=n;i++)
fac[i]=fac[i-1]*i%mod;
c[0][0]=1;
for(int i=1;i<=n;i++)
{
c[i][0]=1;
for(int j=1;j<=i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
for(int i=n;i>=1;i--)
for(int j=i;j<=n;j++)
for(int k=i;k<=j;k++)
{
if(k!=i)
f[i][j]=(f[i][j]+c[j-i][k-i]*f[i][k-1]%mod*fac[j-k]%mod)%mod;
if(k!=j)
f[i][j]=(f[i][j]+c[j-i][k-i]*f[k+1][j]%mod*fac[k-i]%mod)%mod;
if(k!=i&&k!=j)
f[i][j]=(f[i][j]+c[j-i][k-i]*fac[k-i-1]%mod*fac[j-k-1]%mod*(clc(k+1,j)*(k-i)%mod-clc(i,k-1)*(j-k)%mod+mod)%mod)%mod;
}
return (f[1][n]+mod)%mod;
}
};
最新文章
- c/c++ string
- Java--对象池化技术 org.apache.commons.pool2.ObjectPool
- Configure Amazon RDS mysql to store Chinese Characters
- iOS面试题及答案2015.6.7
- jquery ui autoComplete自动完成
- 一个 Android 任务队列的实现
- MySQL生产库主从重新同步操作注意事项
- Html5 Canvas Text
- Linux 修改时区 不用重启
- 批量替换表中某字段的“\t”
- Codeforces 977F - Consecutive Subsequence - [map优化DP]
- [Robot Framework] 通过Robot Remote Server调用White Library测试WPF开发的桌面产品
- Redis发布订阅机制
- ajax提交post请求出现数组被截断情况的解决方法
- js中为什么非要alert一下下一步才会执行
- phpstudy mysql无法启动
- 随想录(skyeye中的soc仿真)
- P1977 出租车拼车(DP)
- NOI2017退役记
- js作用域的几个问题