传送门

分析

我们通过仔细研究不难发现对于一次交换(i,i+1)的操作之后,在i之前的点就不可能跑到i之后,i+1之后的的点也不可能跑到i+1之前,所以这个序列在一次交换之后就相当于被分成了两个部分。于是我们设dp[n][low]表示对于一个长度为n的最小值为low的序列的构成方案数。于是我们可以求出dp[n][low]=dp[i][low]*dp[n-i][low+i]*C(n-2,n-i-1)(i∈(1,n)且此情况合法)。C(n-2,n-i-1)表示在交换这一次之前共要进行n-2次交换,其中n-i-1次是在左边交换,因为选的左右顺序不同是不同的方案,所以要乘上这个值。而至于判断i是否合法见代码。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const long long mod = 1e9+;
long long p[],dp[][],N,c[][];
inline void getc(){
long long i,j,k;
for(i=;i<=;i++)c[i][]=c[i][i]=;
for(i=;i<=;i++)
for(j=;j<i;j++)
c[i][j]=(c[i-][j]+c[i-][j-])%mod;
}
inline long long go(long long n,long long low){
if(dp[n][low]!=-)return dp[n][low];
if(n==)return dp[n][low]=;
long long i,j,k,cnt=,now[];
for(i=;i<=N;i++)if(p[i]>=low&&p[i]<low+n)now[++cnt]=p[i];
dp[n][low]=;
for(i=;i<n;i++){
bool ok=;
swap(now[i],now[i+]);
for(j=;j<=i;j++)if(now[j]>=low+i){ok=;break;}
if(ok){
dp[n][low]=(dp[n][low]+
go(i,low)*go(n-i,low+i)%mod*c[n-][i-]%mod)%mod;
}
swap(now[i],now[i+]);
}
return dp[n][low];
}
int main(){
long long i,j,k;
memset(dp,-,sizeof(dp));
scanf("%lld",&N);getc();
for(i=;i<=N;i++)scanf("%lld",&p[i]);
printf("%lld\n",go(N,));
return ;
}

ZROI2018普转提day2t1的更多相关文章

  1. ZROI2018普转提day6t1

    传送门 分析 记录区间最大值,线段树上二分找比这个点大的最靠前位置即可 代码 #include<iostream> #include<cstdio> #include<c ...

  2. ZROI2018普转提day6t3

    传送门 分析 居然卡哈希数,万恶的出题人...... 感觉我这个方法似乎比较呆,我的代码成功成为了全网最慢的代码qwq 应该是可以直接哈希的 但由于我哈希学的不好又想练练线段树维护哈希,于是就写了个线 ...

  3. ZROI2018普转提day7t1

    传送门 分析 一道有意思的小题... 我们发现如果$(1,1)$为白色,则将其变为白色需要偶数次操作,而如果为黑色则需要奇数次操作 我们知道要让A赢需要奇数次操作,所以我们只需要判断$(1,1)$的颜 ...

  4. ZROI2018普转提day7t2

    传送门 分析 首先我们不难想到我们一定可以将每一个点分开算,然后看这个点被几个矩形包含 于是对于位置为$(i,j)$的点它被包含的次数为$i * (n-i+1) * j * (m-j+1)$ 这个式子 ...

  5. ZROI2018普转提day1t4

    传送门 分析 就是飞飞侠这道题...... 我们可以将这张图建成好几层,每一层可以向下一层的上下左右无代价移动,而对于每个点如果付b[i][j]的代价就可以走到比它高a[i][j]的层上.我们用这种方 ...

  6. ZROI2018普转提day1t1

    传送门 分析 我们先二分一下最终的平均值mid,然后让序列中的每一个数都减去这个mid,之后用新序列的前缀和建一棵线段树,枚举起点i,然后求出此时在i+L-1~i+R-1范围内的前缀和的最大值,用这个 ...

  7. ZROI2018普转提day2t4

    传送门 分析 考场上暴力水过好评... 然后我的st表查询似乎是log的,然后log三方跑的比log方快,qwq. 我们发现如果一个区间的最小值就是这个区间的gcd,则这个区间合法.所以我们二分区间长 ...

  8. ZROI2018普转提day2t2

    传送门 分析 我们发现2R+C实际就相当于R行C列的子集的个数.因此我们可以将所有集合的子集个数转换为每个集合属于的集合的个数.所以我们可以求出: 这个式子的意义为对于选i行j列的情况的所有方案乘上i ...

  9. ZROI2018普转提day2t3

    传送门 分析 考试的时候sb了......我们发现可以按照先序遍历将一棵树变成一个序列,而不需要删的数的数量便是最长上升子序列的长度,但是还有一个问题就是如果在5和7之间有3个空的位置就无法填入合法的 ...

随机推荐

  1. 打印a*a的乘法表

    /*利用for循环打印 9*9 表? 1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 ...

  2. KVO与KVC的使用(转)

    转自http://www.cnblogs.com/mybkn/archive/2013/05/29/3104166.html KVO: 在看KVO之前,有必要先了解下KVC,即,Key-Value C ...

  3. linux进程学习-创建新进程

    init进程将系统启动后,init将成为此后所有进程的祖先,此后的进程都是直接或间接从init进程“复制”而来.完成该“复制”功能的函数有fork()和clone()等. 一个进程(父进程)调用for ...

  4. 以前的实验博客地址,以前使用csdn

    实验一木马分析(隐藏分析)实验 http://blog.csdn.net/qq_30600405/article/details/78360599 实验二木马分析(控制分析)实验和实验三冰河木马实验 ...

  5. java 实现插入排序

    sorted数组第0个位置没有放数据 从sorted数组的第二个数据开始处理 package com.learn; public class InsertionSort { public static ...

  6. npm install -d

    nodejs Error: Cannot find module 'xxx'错误 解决方案: 确定package.json里有添加相应的依赖配置 使用npm install -d 可以自动配置pack ...

  7. C#检查网络是否可以连接互联网

    添加引用: using System.Runtime.InteropServices; using System.Net.NetworkInformation; [DllImport("wi ...

  8. ODP.NET OracleBulkCopy

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using Oracle.DataA ...

  9. Java基础--压缩和解压缩gz包

    gz是Linux和OSX中常见的压缩文件格式,下面是用java压缩和解压缩gz包的例子 public class GZIPcompress { public static void FileCompr ...

  10. mybatis association表关联与rowbounds共同使用时的异常及其解决方案

    按照mybatis手册中所说的,association有两种实现方式,嵌套查询和嵌套结果映射.如手册中所述,select方式会带来N+1次查询的问题,考虑到效率问题的话建议使用嵌套结果映射.但是在结合 ...