CS Academy Distinct Neighbours(经典dp)

题意:

求相邻无相同数字的合法的排列数

题解:

题解

先将相同的数字分为一类,假设共有n组

定义\(dp[i][j]\)表示前i组数字恰好有j对相邻数字相同的方案数,那么最后答案就是dp[n][0]

已经考虑完了前\(i\)组数,现在考虑第\(i+\)组数,如何放置

首先可以枚举放\(k\)个位置,有\(C(cnt[i+1]-1,k-1)\)种放法,然后将这k个位置分成两类

一类放在相同的数字中间 放了\(L\)个位置,有\(C(j,L)\)种那么相邻相同的对数变成\(j - L\)对

一类不放相同的数字中间 放\(k - L\) 个位置,有\(C(S - j,k - L)\)种

最后第\(i+1\)组数 增加了\(cnt[i+1] - k\)对相邻相同的数,即最后变成\(dp[i+1][j - L + cnt[i+1] - k]\)

四层循环 复杂度\(O(n^{3})\)

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 800;
const int mod = 1e9 + 7;
int C[N][N];
void init(){
for(int i = 0;i < N;i++) C[i][0] = C[i][i] = 1;
for(int i = 2;i < N;i++){
for(int j = 1;j <= i;j++){
C[i][j] = (C[i-1][j] + C[i-1][j-1])%mod;
}
}
}
int dp[N][N],cnt[N],total[N];
vector<int> v;
int main(){ init();
int n,x,mx = 1;
cin>>n;
v.push_back(0);
for(int i = 1;i <= n;i++){
cin>>x;
if(!cnt[x]) v.push_back(x);
cnt[x]++;
}
for(int i = 1;i < v.size();i++) total[i] = total[i-1] + cnt[v[i]];
dp[0][0] = 1;
for(int i = 0;i < v.size() - 1;i++){
int num = cnt[v[i+1]],S = total[i]+1;
for(int j = S-1;j >= 0;j--){///j对不同
int kk = min(num,S);///kk个位置可选择
for(int k = 1;k <= kk;k++){
int L = min(j,k);
for(int l = L;S - j >= k - l;l--){
int &res = dp[i+1][j - l + num - k];
res = (res + 1LL * C[num - 1][k - 1] * C[j][l] % mod * C[S-j][k-l]%mod * dp[i][j]%mod)%mod;
}
}
}
}
cout<<dp[v.size()-1][0]<<endl;
return 0;
}

听说还有\(O(n^{2})\)的做法 用到了下面这个东西,研究一下再写写

有\(n_1\)个\(a_1\),\(n_2\)个\(a_2\),...\(n_r\)个\(a_r\)的相邻无相同的排列方法数

\[f(n_1,n_2,...,n_r) = \sum_{1<=t_i<=n_i}^{r}\coprod_{i=1}^{r}(-1)^{n_i-t_i}\binom{n_i-1}{t_i-1}\frac{(t_1+t_2+...+t_r)!}{t_1!t_2!...t_r!}
\]

CS Academy Distinct Neighbours(经典dp)的更多相关文章

  1. CS academy Binary Flips(dp)

    开学啦,没啥时间写博客..过几天就能又停课啦qwq 做点中等 \(dp\) 题来找找 noip 的感觉 233 题意 原题戳这里. 给你一个 \(n \times m\) 的矩阵 \(A\) ,一开始 ...

  2. HDU 1003 Max Sum --- 经典DP

    HDU 1003    相关链接   HDU 1231题解 题目大意:给定序列个数n及n个数,求该序列的最大连续子序列的和,要求输出最大连续子序列的和以及子序列的首位位置 解题思路:经典DP,可以定义 ...

  3. poj1458 求最长公共子序列 经典DP

    Common Subsequence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 45763   Accepted: 18 ...

  4. NYOJ - 矩形嵌套(经典dp)

    矩形嵌套时间限制:3000 ms | 内存限制:65535 KB 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b< ...

  5. 51nod 1412 AVL树的种类(经典dp)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1412 题意: 思路: 经典dp!!!可惜我想不到!! $dp[i][k] ...

  6. NYOJ 16 矩形嵌套(经典DP)

    http://acm.nyist.net/JudgeOnline/problem.php?pid=16 矩形嵌套 时间限制:3000 ms  |           内存限制:65535 KB 难度: ...

  7. poj 1050 To the Max 最大子矩阵和 经典dp

    To the Max   Description Given a two-dimensional array of positive and negative integers, a sub-rect ...

  8. 【经典dp 技巧】8.13序列

    经典的拆绝对值 题目大意 给定$n$个具有顺序的序列,允许对每个序列循环移动.记第$i$个序列尾元素为$x$,$i+1$个序列首元素为$y$,定义其连接收益为$|x-y|*i$,求$n$个序列连接最大 ...

  9. POJ 1160:Post Office 邮局经典DP

    Post Office Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17168   Accepted: 9270 Desc ...

随机推荐

  1. Mybatis-数据插入

    传统jdbc数据插入 1.在Java代码for循环插入 executeUpdate() 2.批处理方法addBatch(Statement.Prestatement) addBatch() execu ...

  2. DNS的主从,转发与负载功能

    接着原来<DNS原理与应用>的文章,本章内容主要通过实现DNS的主从,转发,及基于域名解析不同的ip实现后端服务负载均衡的效果.最后再实现DNS的高级功能:类似CDN原理实现基于IP实现区 ...

  3. datatable设置动态宽度,超过一定长度出现滚动条

    获得宽度:var tableAutoWidth = $('.dataTable_wrapper').width();if (tableAutoWidth < 1200) { tableAutoW ...

  4. 给树莓派Raspbian stretch版本修改软件源

    树莓派最新的系统版本是stretch,试了阿里和网易的软件源都不行,最后试了清华的可以 deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbia ...

  5. 海龟绘图turtle模块的使用

    在本章中,我们将编写简短的.简单的程序来创建漂亮的.复杂的视觉效果.为了做到这一点,我们可以使用海龟作图软件.在海龟作图中,我们可以编写指令让一个虚拟的(想象中的)海龟在屏幕上来回移动.这个海龟带着一 ...

  6. 简单php实现同一时间内一个账户只允许在一个终端登陆

    在账户表的基础上,我新建了一个账户account_session表,用来记录登录账户的account_id和最新一次登录成功用户的session_id,然后首先要修改登录方法:每次登录成功后,要将登录 ...

  7. MySQL 如何查看及修改数据库引擎

    MySQL 如何查看及修改数据库引擎 1.查看mysql支持的引擎有哪些 show engines 结果,如图所示: 由上图可以看出,只有InnoDB是支持事务的 2.查看当前默认的引擎 show v ...

  8. POJ:2566-Bound Found(尺取变形好题)

    Bound Found Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 5408 Accepted: 1735 Special J ...

  9. 从键盘输入数,输出它们的平方值&判断是不是2的阶次方数

    1.从键盘输入两个整数,然后输出它们的平方值和立方值 在Java中,没有像C语言那样有一个专供接受键盘输入值的scanf函数,所以一般的做法是从键盘输入一行字符,保存到字符串s中,再将字符组成的字符串 ...

  10. vlc 编译

    一.有用的网址: https://forum.videolan.org/search.php 二.只编译Java apk部分: source env.shmake distcleanmake -e 编 ...