E. Girl Permutation:
题目大意:
思路解析:
先理解什么是前缀最大值,他应该满足什么条件,根据定义可知对于 i 如果满足 所以 j < i,并且有 ai > aj,那么ai就是前缀最大值, 换言之如果数组 [a1, a2,a3,....,ai] ai是其中的最大值,那么ai就是前缀最大值。
对于后缀最大值有相反的定义, 如果存在数组 [ai,ai+1,ai+2,......,an] ai是其中的最大值,那么ai就是后缀最大值。
那么首先可以确定的是 a1一定是前缀最大值,an一定是后缀最大值。
题目又给出一个是前缀最大值的下标序列和是后缀最大值的下标序列。p数组和s数组,根据上诉分析,p0应该一定是1,sm2应该一定是n。并且pm1 一定等于 s0, 假设pm1 不等于 s0,根据上诉分析我们可以知道,全局最大值一定是前缀最大值和后缀最大值, 假设他的下标为5,那么根据分析 5之后的下标不可能再出现前缀最大值了,5之前的下标不可能出现后缀最大值,因为没有数能比全局最大值还大,那么就可以得出 pm1 一定等于 s0;
那我们可以一开始就确定s0的值就为全局最大值,那么s0之前能选的数 就有的情况,然后就可以这样将整个数组剩下的数分为两半,左右两边互不影响。那么有了这些数假设有k个,现在 1....pi-1....pi没有确定 那么先让pi拿到这k个数的最大值,pi-1拿到这k个数的次大值,然后 pi-1 + 1-- pi - 1在这k-2个数中任意选,然后这些数并且能按照任意顺序进行排列组合。右边类似,那么这样就统计出了每种情况。
代码实现:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main {
static int inf = (int) 2e7;
static int mod = (int) 1e9 + 7;
static int maxN = (int) 2e5;
static long[] fac = new long[maxN+5];
static long[] inv = new long[maxN+5];
public static void main(String[] args) throws IOException {
fac[0] = 1;
for (int i = 1; i <= maxN; i++) {
fac[i] = fac[i-1] * i % mod;
}
inv[0] = 1;
for (int i = 1; i <= maxN; i++) {
inv[i] = qkm(fac[i]);
}
int t = f.nextInt();
while (t > 0) {
solve();
t--;
}
w.flush();
w.close();
br.close();
}
public static void solve() {
int n = f.nextInt(); int A = f.nextInt(); int B = f.nextInt();
int[] a = new int[A]; int[] b = new int[B];
for (int i = 0; i < A; i++) {
a[i] = f.nextInt();
}
for (int i = 0; i < B; i++) {
b[i] = f.nextInt();
}
if (a[0] != 1 || b[B-1] != n || a[A-1] != b[0]) {w.println(0); return;}
else {
long ans = cob(n-1, b[0] -1);
for (int i = A - 2; i >= 0; i--) {
ans = ans * cob(a[i+1] - 2, a[i+1] - a[i] - 1) % mod * fac[a[i+1] - a[i] - 1] % mod;
}
for (int i = 1; i < B; i++) {
ans = ans * cob(n - b[i-1] - 1, b[i] - b[i-1] - 1) % mod * fac[b[i] - b[i-1] - 1] % mod;
}
w.println(ans);
}
}
public static long cob(int n, int k){
return fac[n] * inv[k] % mod * inv[n - k] % mod;
}
public static long qkm(long a){
long b = mod - 2;
long res = 1;
while (b > 0){
if ((b & 1) == 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
String str = null;
try {
str = reader.readLine();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return str;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}
}