time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

The cinema theater hall in Sereja's city is n seats lined up in front of one large screen. There are slots for personal possessions to the left and to the right of each seat. Any two adjacent seats have exactly one shared slot. The figure below shows the arrangement of seats and slots for n = 4.

Today it's the premiere of a movie called "Dry Hard". The tickets for all the seats have been sold. There is a very strict controller at the entrance to the theater, so all n people will come into the hall one by one. As soon as a person enters a cinema hall, he immediately (momentarily) takes his seat and occupies all empty slots to the left and to the right from him. If there are no empty slots, the man gets really upset and leaves.

People are not very constant, so it's hard to predict the order in which the viewers will enter the hall. For some seats, Sereja knows the number of the viewer (his number in the entering queue of the viewers) that will come and take this seat. For others, it can be any order.

Being a programmer and a mathematician, Sereja wonders: how many ways are there for the people to enter the hall, such that nobody gets upset? As the number can be quite large, print it modulo 1000000007 (109 + 7).

Input

The first line contains integer n (1 ≤ n ≤ 105). The second line contains n integers, the i-th integer shows either the index of the person (index in the entering queue) with the ticket for the i-th seat or a 0, if his index is not known. It is guaranteed that all positive numbers in the second line are distinct.

You can assume that the index of the person who enters the cinema hall is a unique integer from 1 to n. The person who has index 1 comes first to the hall, the person who has index 2 comes second and so on.

Output

In a single line print the remainder after dividing the answer by number 1000000007 (109 + 7).

Examples
Input
  1. 11
    0 0 0 0 0 0 0 0 0 0 0
Output
  1. 1024
Input
  1. 6
    0 3 1 0 0 0
Output
  1. 3
  2.  
  3. 给出一个数n还有n个数ci
    如果ci>0,表示排列上的第ci个位置上的数为i
    如果ci=0,表示排列上的第ci个位置上的数不确定
  4.  
  5. 即是说,有一个n的排列,其中部分position上的数固定,求有多少种排列满足:
    对于排列上的任意一个数x,在x之前不同时存在x+1x-12个数的方案数
  6.  
  7. solution:
    这道题主要在于分情况讨论,得到答案
    只要发现一个性质,就可以解决问题了
    要保证对于任意一个数xx+1x-1不同时存在,则x之前的数放在一起刚好是一个[1,n]的子
    区间[L,R],这个自区间的长度为x-1,且有is[x] = L - 1 || is[x] = R + 1
    这样我们只需要分情况讨论,
    部分情况直接推出公式得到答案
    部分情况需要用到递推,同时维护当前的LR
    具体看代码
  8.  
  9. is[i]表示排列的第i个数固定为is[i]
    pre[i]表示第i个数前一个被固定的数,没有则为-1
    next[i]表示第i个数后一个被固定的数,没有则为-1
    f[i]表示当前考虑到排列的第i个数,当前可行的方案数
  10.  
  11. ps
    这道题初始化f的时候要注意细节,分情况初始化
  12.  
  1. //File Name: cf380D.cpp
  2. //Author: long
  3. //Mail: 736726758@qq.com
  4. //Created Time: 2016年05月20日 星期五 00时32分29秒
  5.  
  6. #include <stdio.h>
  7. #include <iostream>
  8. #include <algorithm>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include <map>
  13.  
  14. #define LL long long
  15. #define next NEXT
  16.  
  17. using namespace std;
  18.  
  19. const int MAXN = + ;
  20. const int MOD = (int)1e9 + ;
  21.  
  22. int is[MAXN], pre[MAXN], next[MAXN];
  23. LL f[MAXN],jie[MAXN];
  24.  
  25. void init(int n){
  26. jie[] = ;
  27. for(int i=;i<=n;i++)
  28. jie[i] = jie[i-] * i % MOD;
  29. int now = -;
  30. for(int i=;i<=n;i++){
  31. pre[i] = now;
  32. if(is[i]) now = i;
  33. }
  34. now = -;
  35. for(int i=n;i>;i--){
  36. next[i] = now;
  37. if(is[i]) now = i;
  38. }
  39. }
  40.  
  41. LL qp(LL x,LL y){
  42. LL res = ;
  43. while(y){
  44. if(y & ) res = res * x % MOD;
  45. x = x * x % MOD;
  46. y >>= ;
  47. }
  48. return res;
  49. }
  50.  
  51. LL get_c(LL x,LL y){
  52. if(y < || x < y) return ;
  53. if(y == || y == x) return ;
  54. return jie[x] * qp(jie[y] * jie[x - y] % MOD,MOD - ) % MOD;
  55. }
  56.  
  57. LL solve(int n,bool flag){
  58. if(!flag) return qp(,n - );
  59. init(n);
  60. //for(int i=1;i<=n;i++){
  61. // printf("i = %d is = %d\n",i,is[i]);
  62. //}
  63. int L = n + , R = ;
  64. for(int i=;i<=n;i++){
  65. if(!is[i]) continue;
  66. if(L <= is[i] && R >= is[i])
  67. return ;
  68. if(pre[i] == - && next[i] == -){
  69. LL ans = ,now;
  70. for(int x=;x < is[i];x++){
  71. now = get_c(i-,x) * get_c(n-i,is[i]-x-) % MOD;
  72. if(x > ) ans = (ans + now * % MOD) % MOD;
  73. else ans = (ans + now) % MOD;
  74. }
  75. return ans;
  76. }
  77. else if(pre[i] > ){
  78. f[i] = f[pre[i]];
  79. //printf("i = %d pre = %d next = %d f = %d\n",i,pre[i],next[i],f[i]);
  80. if(is[i] > is[pre[i]]) R++;
  81. else L--;
  82. //printf("L = %d R = %d\n",L,R);
  83. if(next[i] == -){
  84. return f[i] * get_c(n-i,L-) % MOD;
  85. }
  86. else{
  87. if(is[next[i]] > R){
  88. //printf("i = %d f = %d\n",i,f[i]);
  89. f[i] = f[i] * get_c(next[i]-i-,is[next[i]]-R-) % MOD;
  90. R = is[next[i]] - ;
  91. L = R + - next[i];
  92. //printf("i = %d f = %d\n",i,f[i]);
  93. }
  94. else{
  95. //printf("i = %d f = %d\n",i,f[i]);
  96. f[i] = f[i] * get_c(next[i]-i-,L-is[next[i]]-) % MOD;
  97. L = is[next[i]] + ;
  98. R = L + next[i] - ;
  99. //printf("i = %d f = %d\n",i,f[i]);
  100. }
  101. }
  102. //printf("L = %d R = %d\n",L,R);
  103. }
  104. else{
  105. if(is[i] < is[next[i]]){
  106. R = is[next[i]] - ;
  107. L = R + - next[i];
  108. }
  109. else{
  110. L = is[next[i]] + ;
  111. R = L + next[i] - ;
  112. }
  113. int cnt = abs(is[next[i]] - is[i]);
  114. f[i] = ;
  115. if(i == ){
  116. f[i] = get_c(next[i]-,R-is[i]);
  117. }
  118. else{
  119. //printf("is = %d L = %d R = %d\n",is[i],L,R);
  120. if(i- <= is[i]-L)
  121. f[i] = qp(,i-) * get_c(next[i]-i-,is[i]-L-i+) % MOD;
  122. //printf("f = %d\n",f[i]);
  123. if(i- <= R-is[i])
  124. (f[i] += qp(,i-) * get_c(next[i]-i-,R-is[i]-i+)% MOD) %= MOD;
  125. //printf("f = %d\n",f[i]);
  126. }
  127. //printf("i = %d pre = %d next = %d f = %d\n",i,pre[i],next[i],f[i]);
  128. //printf("L = %d R = %d\n",L,R);
  129. }
  130. }
  131. return -;
  132. }
  133.  
  134. int main(){
  135. int n,u;
  136. bool flag = false;
  137. scanf("%d",&n);
  138. memset(is,,sizeof is);
  139. for(int i=;i<=n;i++){
  140. scanf("%d",&u);
  141. if(u){
  142. is[u] = i;
  143. flag = true;
  144. }
  145. }
  146. printf("%d\n",(int)solve(n,flag));
  147. return ;
  148. }
  1.  

cf380D Sereja and Cinema 组合数学的更多相关文章

  1. Codeforces 380D Sereja and Cinema (看题解)

    Sereja and Cinema 首先我们可以发现除了第一个人, 其他人都会坐在已入坐人的旁边. 难点在于计算方案数.. 我们可以从外往里把确定的人用组合数算上去,然后缩小范围. #include& ...

  2. Codeforces 380 简要题解

    ABC见上一篇. 感觉这场比赛很有数学气息. D: 显然必须要贴着之前的人坐下. 首先考虑没有限制的方案数.就是2n - 1(我们把1固定,其他的都只有两种方案,放完后长度为n) 我们发现对于一个限制 ...

  3. CodeForces - 896D :Nephren Runs a Cinema(卡特兰数&组合数学---比较综合的一道题)

    Lakhesh loves to make movies, so Nephren helps her run a cinema. We may call it No. 68 Cinema. Howev ...

  4. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  5. CF380C. Sereja and Brackets[线段树 区间合并]

    C. Sereja and Brackets time limit per test 1 second memory limit per test 256 megabytes input standa ...

  6. Codeforces #380 div2 C(729C) Road to Cinema

    C. Road to Cinema time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  7. poj 3734 Blocks 快速幂+费马小定理+组合数学

    题目链接 题意:有一排砖,可以染红蓝绿黄四种不同的颜色,要求红和绿两种颜色砖的个数都是偶数,问一共有多少种方案,结果对10007取余. 题解:刚看这道题第一感觉是组合数学,正向推了一会还没等推出来队友 ...

  8. 组合数学or not ---- n选k有重

    模板问题: 1. 取物品 (comb.pas/c/cpp) [问题描述] 现在有n个物品(有可能相同),请您编程计算从中取k个有多少种不同的取法.[输入] 输入文件有两行,第一行包含两个整数n,k(2 ...

  9. 组合数学(全排列)+DFS CSU 1563 Lexicography

    题目传送门 /* 题意:求第K个全排列 组合数学:首先,使用next_permutation 函数会超时,思路应该转变, 摘抄网上的解法如下: 假设第一位是a,不论a是什么数,axxxxxxxx一共有 ...

随机推荐

  1. 后台向前台传递entity的list然后构筑combobox的方法(easyui)

    遇问题,莫着急,深呼吸. 后台写法:JsonUtil.toJson(new ArrayList<Entity>());此处jsonUtil是已封装的方法,即将entity的list转为js ...

  2. c语言开发手机通讯录

    // //  main.c //  手机通讯录 // //  Created by Kevin-Dfg on 16/4/19. //  Copyright © 2016年 Kevin-Dfg. All ...

  3. VPS 搭建 SS

    推荐 VPS:http://www.vultr.com/?ref=6915101 1.连接 VPS 运行命令 ssh root@xx.xx.xx.xx -p 22 // vultr 的端口为 22 然 ...

  4. MFC-CString 字符串分割

    CString strSrc = _T("1++2+3+4"); CStringArray strResult; CString strGap = _T("+" ...

  5. Scrum 项目2.0

    阅读教材第8章,8.1~8.3节 P157~168,了解获取用户需求的办法,每个组可以选择一二加以应用. 8.4节P168-171 查阅NABCDA模型的具体说明. 2.SCRUM 流程的步骤 1 完 ...

  6. linux下crontab定时执行本地脚本和定时访问指定url

    https://my.oschina.net/u/2487410/blog/683308 使用linux curl命令讲解:http://www.linuxdiyf.com/linux/2800.ht ...

  7. ARTICLES

    https://blogs.msdn.microsoft.com/tess/2005/12/20/things-to-ignore-when-debugging-an-asp-net-hang/ ht ...

  8. form表单回车提交问题,JS监听回车事件

    我们有时候希望回车键敲在文本框(input element)里来提交表单(form),但有时候又不希望如此.比如搜索行为,希望输入完关键词之后直接按回车键立即提交表单,而有些复杂表单,可能要避免回车键 ...

  9. Uncaught TypeError: Illegal constructor(…)

    使用jquery  $(Document);会报这个错误.因为 Document(大写) 是函数. document(小写) 才是文档.

  10. 开放平台-web实现人人网第三方登录

    应用场景     web应用通过人人网登录授权实现第三方登录.   操作步骤     1  注册成为人人网开放平台开发者         http://app.renren.com/developer ...