## $>Topcoder \space Srm \space 673 \space Div2 \space 1000 \space BearPermutations2

题目大意 : 对于一个长度为 \(n\) 的排列,定义其的贡献为对其建笛卡尔树,树上有两个儿子的节点其左右儿子在原排列中的距离之和,给出 \(n, Mod\),求所有长度为 \(n\) 的排列的贡献之和对 \(Mod\) 取模的值

\(1 \leq n \leq 100\)

解题思路 :

考虑一个最暴力的 \(dp\) ,设 \(f[i][j][k]\) 表示区间 \([i, j]\) 的极值在 \(k\) 上的答案

每次的转移的贡献由两部分组成,其一是划分成的左右区间的答案乘上排列数,其二是左右儿子产生的贡献

第一种贡献十分简单,在此不多做讨论,主要考虑第二种贡献

考虑最暴力的转移,枚举左边的极值的位置 \(l\), 和最右边的极值 \(r\) ,那么中间的贡献就是

\(\sum_{l=i}^{k-1}\sum_{k+1}^{j} (k-i-1)! \times(j-k-1)!\times(r - l)\)

观察发现,无论 \(l, r\) 的取值是多少,它的排列数都等同于一个位置固定剩下随便排的方案数

也就是说,排列数只和左右区间的大小有关,和极值的具体位置无关

所以我们可以不必在状态中记极值的位置,直接枚举当且区间的极值是什么然后拿划分成的左右区间转移

再回到之前的转移式子,观察发现只要对这个式子稍加变换就能把 \(\sum\) 符号去掉

首先把排列数提出来 \((k-i-1)! \times(j-k-1)!\times\sum_{l=i}^{k-1}\sum_{k+1}^{j} (r - l)\)

设 $sum(i, j) $ 表示 \(i + (i + 1) +..+ j\) 的和,这个可以 \(O(1)\) 计算,把 \(sum()\) 代入式子得

\((k-i-1)! \times(j-k-1)!\times [sum(k+1, j) \times (k - i) - sum(i, k-1) \times (j-k)]\)

经过基础的推式子之后,我们省去了对极值所在位置的在状态上的记录,并且将枚举左右两个极值位置的 \(\sum\) 消去

所以状态变为 \(f[i][j]\) 表示所有排列在区间 \([i,j]\) 上的答案

转移方程变成了

\(f[i][j] = \sum_{k=i}^{j} C_{j-i}^{k-1}\times \{(f[i][k-1] \times(j-k)!)+(f[k+1][j] \times(k-i)!) + (k-i-1)! \times(j-k-1)!\times [sum(k+1, j) \times (k - i) - sum(i, k-1) \times (j-k)]\}\)

复杂度变成了 \(O(n^3)\)

事实上还可以观察发现,对于大小相同的区间其\(f\)值是一样,可以记\(f_i\) 表示长度为 \(i\) 的区间的答案,枚举其可能的子区间大小转移

这个方程会是一个卷积的形式,所以可以通过 \(FFT\) 来优化复杂度,不过 \(O(n^3)\) 的算法已经可以解决此题,这个算法就不过多讨论了

/*program by mangoyang*/
typedef long long ll;
ll f[1005][1005], g[1005][1005], js[1005], Mod, n, ans;
inline ll C(ll n, ll i){ return f[n][i]; }
inline ll sum(ll l, ll r){ return ((l + r) * (r - l + 1) / 2) % Mod; }
inline ll Pow(ll a, ll b){
ll ans = 1;
for(; b; b >>= 1, a = a * a % Mod)
if(b & 1) ans = ans * a % Mod;
return ans;
}
int BearPermutations2::getSum(int N, int MOD) {
n = N, Mod = MOD, ans = 0, js[0] = 1;
for(int i = 1; i <= n; i++) js[i] = js[i-1] * i % Mod;
memset(f, 0, sizeof(f)), memset(g, 0, sizeof(g));
for(int i = 0; i <= n; i++) f[i][0] = 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= i; j++) f[i][j] = (f[i-1][j-1] + f[i-1][j]) % 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) (g[i][j] += C(j - i, k - i) * g[i][k-1] % Mod * js[j-k] % Mod) %= Mod;
if(k < j) (g[i][j] += C(j - i, k - i) * g[k+1][j] % Mod * js[k-i] % Mod) %= Mod;
if(k == i || k == j) continue;
ll tmp = js[k-i-1] * js[j-k-1] % Mod * C(j - i, k - i) % Mod;
ll now = ((sum(k + 1, j) * (k - i) % Mod) - (sum(i, k - 1) * (j - k) % Mod) + Mod) % Mod;
g[i][j] = (g[i][j] + now * tmp % Mod) % Mod;
}
}
return g[1][n];
}

Topcoder Srm 673 Div2 1000 BearPermutations2的更多相关文章

  1. Topcoder Srm 671 Div2 1000 BearDestroysDiv2

    \(>Topcoder \space Srm \space 671 \space Div2 \space 1000 \space BearDestroysDiv2<\) 题目大意 : 有一 ...

  2. TopCoder SRM 660 Div2 Problem 1000 Powerit (积性函数)

    令$f(x) = x^{2^{k}-1}$,我们可以在$O(k)$的时间内求出$f(x)$. 如果对$1$到$n$都跑一遍这个求解过程,时间复杂度$O(kn)$,在规定时间内无法通过. 所以需要优化. ...

  3. TopCoder SRM 301 Div2 Problem 1000 CorrectingParenthesization(区间DP)

    题意  给定一个长度为偶数的字符串.这个字符串由三种括号组成. 现在要把这个字符串修改为一个符合括号完全匹配的字符串,改变一个括号的代价为$1$,求最小总代价. 区间DP.令$dp[i][j]$为把子 ...

  4. SRM 146 DIV2 1000

    Problem Statement      A well-known riddle goes like this: Four people are crossing an old bridge. T ...

  5. 求拓扑排序的数量,例题 topcoder srm 654 div2 500

    周赛时遇到的一道比较有意思的题目: Problem Statement      There are N rooms in Maki's new house. The rooms are number ...

  6. Topcoder srm 632 div2

    脑洞太大,简单东西就是想复杂,活该一直DIV2; A:水,基本判断A[I]<=A[I-1],ANS++; B:不知道别人怎么做的,我的是100*N*N;没办法想的太多了,忘记是连续的数列 我们枚 ...

  7. topcoder SRM 628 DIV2 BracketExpressions

    先用dfs搜索所有的情况,然后判断每种情况是不是括号匹配 #include <vector> #include <string> #include <list> # ...

  8. topcoder SRM 628 DIV2 BishopMove

    题目比较简单. 注意看测试用例2,给的提示 Please note that this is the largest possible return value: whenever there is ...

  9. Topcoder SRM 683 Div2 B

    贪心的题,从左向右推过去即可 #include <vector> #include <list> #include <map> #include <set&g ...

随机推荐

  1. POj 2104 K-th Number (分桶法+线段树)

    题目链接 Description You are working for Macrohard company in data structures department. After failing ...

  2. Spring Boot中配置文件application.properties使用

    一.配置文档配置项的调用 启动后在浏览器直接输入http://localhost:18080/user/test,就直接打印出配置文件中的配置内容. 二.绑定对象bean调用 有时候属性太多了,一个个 ...

  3. mysql in/no in/like

    % 任意字符 _ 任意一个字符 in (value,......) 在这里 not in (value,......) 不在这里 mysql> select 'a' not in (1,2,3, ...

  4. Java多态的实现原理

    1.多态的定义:指允许不同类的对象,对同一消息作出响应: 即同一消息可以根据发送对象的不同采用多种不同的行为方式: 2.多态的实现技术:动态绑定: 指在执行期间判断所引用对象的实际类型,根据其实际的类 ...

  5. 基于ARM 构架(带MMU)的copy_from_user与copy_to_user详细分析

      [转自:http://blog.chinaunix.net/uid-20543672-id-3195249.html]   在学习Linux内核驱动的时候,一开始就会碰到copy_from_use ...

  6. windows7 能连接移动硬盘 无法显示盘符

    右键点我的电脑,管理里,点磁盘管理,看盘认到没,有时候认到了但是没给盘符,需要自己手动给一个

  7. 用selenium 模块控制浏览器

    11.8 用selenium 模块控制浏览器selenium 模块让Python 直接控制浏览器,实际点击链接,填写登录信息,几乎就像是有一个人类用户在与页面交互.与Requests 和Beautif ...

  8. 【uva11248】网络扩容

    网络流裸题. 求完最大流之后保留残余容量信息,依次将已经加入最小割的弧变成c再跑,记录下即可. #include<bits/stdc++.h> #define N 20005 #defin ...

  9. vue 计算属性 实例选项 生命周期

    vue 计算属性: computed:{} 写在new vue()的属性,只要参与运算,数据不发生变化时,次计算只会执行一次,结果缓存,之后的计算会直接从缓存里去结果.如果其中的值发生变化(不管几个) ...

  10. django开发项目实例2--如何链接图片和css文件(静态文件)

    在上一篇随笔里面,我们已经介绍了如何从零开始用django建立一个项目并且初步运行以来了, 现在我们就要开始写我们的html了,也就是django里面的模板了,不过这节我们只讲如何链接图片和css(静 ...