题目大意

  有一个长度为序列 \(a\),其中某些位置的值是 \(-1\)。

  你要把 \(a\) 补成一个排列。

  定义 \(b_i=\min(a_{2i-1},a_{2i})\),求有多少种可能的 \(b\)。

  \(n\leq 300\)

题解

  如果 \(a_{2i-1}\) 和 \(a_{2i}\) 都有值,就把这两个位置扔掉。

  记 \(c_i\) 表示 \(i\) 这个值是否在初始的 \(a\) 中。

  从后往前DP。记 \(f_{i,j,k}\) 表示已经处理完了 \(i\) 后面的数,有多少个 \(j>i,c_j=1\) 的数匹配的是 \(\leq i\) 的数,有多少个 \(j>i,c_j=0\) 的数匹配的是 \(\leq i\) 的数。

  如果 \(c_i=1\) 且往后匹配的是 \(c_j=0\),那么方案数为 \(1\)。(因为 \(\min=i\))

  如果 \(c_i=0\) 且往后匹配的是 \(c_j=0\),那么先暂定方案数为 \(1\)。(因为暂时不能确定 \(i\) 填在哪个位置。)记这种匹配对数为 \(cnt\)。

  如果 \(c_i=0\) 且往后匹配的是 \(c_j=1\),那么方案数为 \(j\)。(因为可以确定 \(i\) 填在哪个位置。)

  最后方案数要乘上 \(cnt!\),因为这些位置的 \(b\) 可以随便交换。

  时间复杂度:\(O(n^3)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
//using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
using std::vector;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
void open2(const char *s){
#ifdef DEBUG
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const ll p=1000000007;
const int N=310;
void add(ll &a,ll b)
{
a=(a+b)%p;
}
int n;
int a[2*N];
ll f[2*N][N][N];
int b[2*N];
int c[2*N];
int t;
int main()
{
open2("f");
scanf("%d",&n);
for(int i=1;i<=2*n;i++)
scanf("%d",&a[i]);
int cnt=0;
for(int i=1;i<=2*n;i+=2)
if(a[i]!=-1&&a[i+1]!=-1)
b[a[i]]=b[a[i+1]]=2;
else if(a[i]!=-1)
b[a[i]]=1;
else if(a[i+1]!=-1)
b[a[i+1]]=1;
else
cnt++;
for(int i=1;i<=2*n;i++)
if(b[i]==1)
c[++t]=1;
else if(b[i]==0)
c[++t]=2;
f[t][0][0]=1;
for(int i=t;i>=1;i--)
for(int j=0;j<=t&&j<=n;j++)
for(int k=0;k<=t&&k<=n;k++)
if(c[i]==1)
{
add(f[i-1][j+1][k],f[i][j][k]);
if(k)
add(f[i-1][j][k-1],f[i][j][k]);
}
else
{
add(f[i-1][j][k+1],f[i][j][k]);
if(k)
add(f[i-1][j][k-1],f[i][j][k]);
if(j)
add(f[i-1][j-1][k],f[i][j][k]*j);
}
ll ans=f[0][0][0];
for(int i=1;i<=cnt;i++)
ans=ans*i%p;
printf("%lld\n",ans);
return 0;
}

【AGC030F】Permutation and Minimum DP的更多相关文章

  1. 【agc030f】Permutation and Minimum(动态规划)

    [agc030f]Permutation and Minimum(动态规划) 题面 atcoder 给定一个长度为\(2n\)的残缺的排列\(A\),定义\(b_i=min\{A_{2i-1},A_{ ...

  2. 【AGC030F】Permutation and Minimum(DP)

    题目链接 题解 首先可以想到分组后,去掉两边都填了数的组. 然后就会剩下\((-1,-1)\)和\((-1,x)\)或\((x,-1)\)这两种情况 因为是最小值序列的情况数,我们可以考虑从大到小填数 ...

  3. 【BZOJ4712】洪水(动态dp)

    [BZOJ4712]洪水(动态dp) 题面 BZOJ 然而是权限题QwQ,所以粘过来算了. Description 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开 ...

  4. 【题解】Jury Compromise(链表+DP)

    [题解]Jury Compromise(链表+DP) 传送门 题目大意 给你\(n\le 200\)个元素,一个元素有两个特征值,\(c_i\)和\(d_i\),\(c,d \in [0,20]\), ...

  5. 【题解】Making The Grade(DP+结论)

    [题解]Making The Grade(DP+结论) VJ:Making the Grade HNOI-D2-T3 原题,禁赛三年. 或许是我做过的最简单的DP题了吧(一遍过是什么东西) 之前做过关 ...

  6. 【题解】NOIP2017逛公园(DP)

    [题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n​节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...

  7. 【题解】284E. Coin Troubles(dp+图论建模)

    [题解]284E. Coin Troubles(dp+图论建模) 题意就是要你跑一个完全背包,但是要求背包的方案中有个数相对大小的限制 考虑一个\(c_i<c_j\)的限制,就是一个\(c_i\ ...

  8. 【LeetCode】153. Find Minimum in Rotated Sorted Array 解题报告(Python)

    [LeetCode]153. Find Minimum in Rotated Sorted Array 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode. ...

  9. 【LeetCode】154. Find Minimum in Rotated Sorted Array II 解题报告(Python)

    [LeetCode]154. Find Minimum in Rotated Sorted Array II 解题报告(Python) 标签: LeetCode 题目地址:https://leetco ...

随机推荐

  1. winform登录功能

    private void btnLogin_Click(object sender, EventArgs e) { string username = txtUserName.Text; string ...

  2. 享元模式 FlyWeight 结构型 设计模式(十五)

    享元模式(FlyWeight)  “享”取“共享”之意,“元”取“单元”之意. 意图 运用共享技术,有效的支持大量细粒度的对象. 意图解析 面向对象的程序设计中,一切皆是对象,这也就意味着系统的运行将 ...

  3. MongoDB学习(管理数据库和集合)

    管理数据库 显示数据库列表 show dbs 切换到其他数据库 use <database_name> 创建数据库 MongoDB没有提供显式的创建数据库的MongoDB shell命令. ...

  4. W3C 代码标准规范

    W3C通过设立领域(Domains)和标准计划(Activities)来组织W3C的标准活动,围绕每个标准计划,会设立相关的W3C工作组织(包括工作组.社区组.商务组等).W3C会根据产业界的标准需求 ...

  5. arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  6. Android设计模式总结

    1.复合模式:三层架构.MVC.MVP.MVVM 2.设计模式-单例模式 配置类的使用. 3.设计模式-模板方法 通过抽象类或接口提前定义要实现的方法. 4.设计模式-观察者模式 消息的通知. 5.设 ...

  7. Centos7 使用 kubeadm 安装Kubernetes 1.13.3

    目录 目录 什么是Kubeadm? 什么是容器存储接口(CSI)? 什么是CoreDNS? 1.环境准备 1.1.网络配置 1.2.更改 hostname 1.3.配置 SSH 免密码登录登录 1.4 ...

  8. centos7后台服务部署jar包

    centos7 服务部署jar包 centos7 服务介绍 CentOS7的服务systemctl脚本存放在:/usr/lib/systemd/,有系统(system)和用户(user)之分, 每一个 ...

  9. 从0开始的Python学习017Python标准库

    简介 Python标准库使随着Python附带安装的,它包含很多有用的模块.所以对一个Python开发者来说,熟悉Python标准库是十分重要的.通过这些库中的模块,可以解决你的大部分问题. sys模 ...

  10. NVIDIA-SMI系列命令总结

    1  NVIDIA-SMI介绍 nvidia-smi简称NVSMI,提供监控GPU使用情况和更改GPU状态的功能,是一个跨平台工具,它支持所有标准的NVIDIA驱动程序支持的Linux发行版以及从Wi ...