题目链接

https://atcoder.jp/contests/agc030/tasks/agc030_f

题解

首先序列里会有\(a_{2i-1}\)和\(a_{2i}\)都不为\(-1\)的情况,显然不影响,去掉即可。
对于\(a_{2i-1}\)和\(a_{2i}\)之一为\(-1\)的\(i\), 将二者中不为\(-1\)的称作“特殊数”,其余的称作“一般数”。
然后考虑从大到小DP. 设\(f[i][j][k]\)表示考虑\(\ge i\)的数,还有\(j\)个一般数的组和\(k\)个特殊数的组缺一个数。
直接转移即可。若\(i\)是一般数,则可以新开一组(转移至\(f[i-1][j+1][k]\)),可以和一般数匹配(转移至\(f[i-1][j-1][k]\)),可以和特殊数匹配(乘\(k\)后转移至\(f[i-1][j][k-1]\));若\(i\)是特殊数,则可以新开一组(转移至\(f[i-1][j][k+1]\)),可以和一般数匹配(转移至\(f[i-1][j-1][k]\))。最终答案乘以\(a_{2i-1}=a_{2i}=-1\)的\(a\)的个数的阶乘即可。
时间复杂度\(O(n^3)\).

如果按照同样的方法从小到大DP,会出现的问题是: (1) 同一个\(b\)序列的方案会出现在多个\(f[i][j][k]\)中。例如拿大的一般数匹配小的数的时候,小的数既可以是一般数又可以是特殊数,因而同一个\(b\)序列会被转移到\(f[i+1][j-1][k]\)和\(f[i+1][j][k-1]\). 而从大到小可以有效避免这个问题,因为拿\(i\)匹配更大的数时\(i\)一定出现在\(b\)序列中。 (2) 举个例子: 当\(i=5\),特殊数为\(3\)和\(6\)时,\((1,3)(4,5)(2)\)和\((1,3)(2,5)(4)\)是同一种方案。但实际上当添加特殊数\(6\)时,由于特殊数位置是固定的,\((1,3)(4,5)(2,6)\)和\((1,3)(2,5)(4,6)\)是不同的方案,因此会算漏。但从大到小不会出现这个问题,因为它的匹配是拿小的一般数去选大的特殊数,而特殊数之间是有顺序的,会被算作不同的方案。

代码

#include<bits/stdc++.h>
#define llong long long
using namespace std;inline int read()
{int x = 0,f = 1; char ch = getchar();for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}return x*f;
}const int N = 300;
const int P = 1e9+7;
llong f[N+N+3][N+3][N+3];
int a[N+N+3];
bool used[N+N+3];
vector<int> vec;
int n;llong updsum(llong &x,llong y) {x = x+y>=P?x+y-P:x+y;}int main()
{scanf("%d",&n); int cnt1 = 0,cnt2 = 0;for(int i=1; i<=n; i++){scanf("%d%d",&a[i+i-1],&a[i+i]);if(a[i+i-1]!=-1&&a[i+i]!=-1){vec.push_back(a[i+i-1]),vec.push_back(a[i+i]);i--,n--;}else if(a[i+i-1]==-1&&a[i+i]==-1) {cnt1++;}else {cnt2++;}}sort(vec.begin(),vec.end());for(int i=1; i<=n+n; i++) {a[i] -= (lower_bound(vec.begin(),vec.end(),a[i])-vec.begin());}
//  printf("a: "); for(int i=1; i<=n+n; i++) printf("%d ",a[i]); puts("");for(int i=1; i<=n+n; i++) if(a[i]!=-1) {used[a[i]] = true;}f[n+n+1][0][0] = 1ll;for(int i=n+n+1; i>=2; i--){for(int j=0; j<=cnt1+cnt2; j++){for(int k=0; k<=cnt2; k++){llong x = f[i][j][k]; if(!x) continue;if(!used[i-1]){updsum(f[i-1][j+1][k],x);if(j>0) {updsum(f[i-1][j-1][k],x);}updsum(f[i-1][j][k-1],x*k%P);}else{updsum(f[i-1][j][k+1],x);if(j>0) {updsum(f[i-1][j-1][k],x);}}}}}llong ans = f[1][0][0]; int tmp = 0;for(int i=1; i<=n; i++) tmp += (a[i+i-1]==-1)&&(a[i+i]==-1);while(tmp) {ans = ans*tmp%P; tmp--;}printf("%lld\n",ans);return 0;
}

AtCoder AGC030F Permutation and Minimum (DP、计数)相关推荐

  1. AtCoder4515 [AGC030F] Permutation and Minimum(dp)

    problem 洛谷链接 solution 一个 AiA_iAi​ 只会影响一个 BiB_iBi​,BiB_iBi​ 之间的决定因素 AAA 是不会有交的. 所以如果相邻两个对同一个 BiB_iBi​ ...

  2. Atcoder AGC031B Reversi (DP计数)

    Atcoder AGC031B Reversi (DP计数) 简单的计数题.(总算做出一道AGC的B题了,然而这场比赛我忘记打了233333) 题目链接: https://atcoder.jp/con ...

  3. AtCoder Grand Contest 030F - Permutation and Minimum

    题意: 设 b i = m i n ( a 2 i , a 2 i − 1 ) b_i=min(a_{2i},a_{2i-1}) bi​=min(a2i​,a2i−1​) 先给出 a a a部分,将其 ...

  4. atcoder A - Frog 1(DP)

    A - Frog 1 Time Limit: 2 sec / Memory Limit: 1024 MB Score : 100100 points Problem Statement There a ...

  5. F - Tmutarakan Exams URAL - 1091 -莫比乌斯函数-容斥 or DP计数

    F - Tmutarakan Exams 题意 : 从 < = S 的 数 中 选 出 K 个 不 同 的 数 并 且 gcd > 1 .求方案数.   思路 :记 录 一 下 每 个 数 ...

  6. AtCoder AGC019E Shuffle and Swap (DP、FFT、多项式求逆、多项式快速幂)

    题目链接 https://atcoder.jp/contests/agc019/tasks/agc019_e 题解 tourist的神仙E题啊做不来做不来--这题我好像想歪了啊= =-- 首先我们可以 ...

  7. BZOJ 2281 Luogu P2490 [SDOI2011]黑白棋 (博弈论、DP计数)

    怎么SDOI2011和SDOI2019的两道题这么像啊..(虽然并不完全一样) 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?i ...

  8. 【AtCoder - 4244 】AtCoder Express 2 (区间dp 或 暴力枚举,思维)

    题干: In Takahashi Kingdom, there is a east-west railroad and N cities along it, numbered 1, 2, 3, ... ...

  9. Atcoder 077E - guruguru(线段树+dp)

    题目链接:http://arc077.contest.atcoder.jp/tasks/arc077_c 分析:如果某条线段包含x,显然应该先按一下到x,再从x走,反之必然是直接走过去,很容易想到用d ...

最新文章

  1. sevlet表单处理无法相应问题及web.xml配置.
  2. 转载一个不错的LRU cache
  3. 堆之大,ZGC亦可速清也!
  4. vscode 格式化json
  5. javascript 数组所有方法
  6. sql服务器数据库主文件,数据库文件和文件组
  7. CentOS7安装MySQL8报错mariadb-libs is obsoleted by mysql-community-libs-8.0.xx-1.el7.x86_64
  8. Stata数据处理:物价指数-(CPI)-的导入和转换
  9. 将照片修改成一寸大小
  10. 单反相机的传奇—佳能单反50年辉煌之路(连载十八)
  11. 定位input的光标,设置光标的位置
  12. 2021最新最全前端面试题(包含HTML、CSS、JavaScript、Vue、React、浏览器、算法与数据结构等)
  13. win7下开启wifi热点共享网络的方法
  14. 领域驱动设计(DDD)在爱奇艺打赏业务的实践
  15. 面包店算法c语言,Lamport面包店算法
  16. 关于 ping-pong buff
  17. Linux 线程同步
  18. 智慧水务信息化系统建设方案
  19. 详解正则中先行断言的用法
  20. 从终端进入本地其他磁盘

热门文章

  1. 台湾大学林轩田机器学习基石课程学习笔记10 -- Logistic Regression
  2. ModuleNotFoundError: No module named 'mpl_toolkits.basemap'
  3. java获取2017年第39周_java中怎么样取出39周的每周开始时间和每周结束时间?
  4. 3DSlicer5:开发者必晓ABC
  5. JavaScript 模拟事件触发
  6. c++中实现delphi的按类名生成类对象
  7. JavaScript事件绑定的方法说明 收藏
  8. 设计一个函数能够取出字符串中指定的字符
  9. 交换技术、覆盖技术、虚拟存储技术的区分
  10. 也谈SSDT Hook(一)