题意
挺简洁的。
我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件:
(1)它是从1到2n共2n个整数的一个排列{ai};
(2)所有的奇数项满足a1<a3<…<a2n-1,所有的偶数项满足a2<a4<…<a2n;
(3)任意相邻的两项a2i-1与a2i(1≤i≤n)满足奇数项小于偶数项,即:a2i-1<a2i。
现在的任务是:对于给定的n,请求出有多少个不同的长度为2n的有趣的数列。因为最后的答案可能很大,所以只要求输出答案 mod P的值。
Sol
打表后发现时Catalan数。
通项公式:$\frac{C_{2n}^n}{n + 1}$
/* */ #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<vector> #include<set> #include<queue> #include<cmath> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/hash_policy.hpp> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second //#define int long long #define LL long long #define rg register #define sc(x) scanf("%d", &x); #define pt(x) printf("%d ", x); #define db(x) double x #define rep(x) for(int i = 1; i <= x; i++) //#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++) //char buf[(1 << 22)], *p1 = buf, *p2 = buf; char obuf[1<<24], *O = obuf; #define OS *O++ = ' '; using namespace std; using namespace __gnu_pbds; const int MAXN = 1e5 + 10, INF = 1e9 + 10, mod = 1e9 + 7; const double eps = 1e-9; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N; int a[MAXN], js[MAXN]; bool check() { for(int i = 1; i <= N - 2; i += 2) if(a[i] >= a[i + 2]) return 0; for(int i = 1; i <= N - 1; i += 2) if(a[i] >= a[i + 1]) return 0; for(int i = 2; i <= N - 2; i += 2) if(a[i] >= a[i + 2]) return 0; return 1; } main() { while(1) { N = read() << 1; js[0] = 1; for(int i = 1; i <= N; i++) js[i] = i * js[i - 1]; for(int i = 1; i <= N; i++) a[i] = i; int ans = 0; for(int i = 1; i <= js[N]; i++) { if(check()) ans++; next_permutation(a + 1, a + N + 1); } printf("%d\n", ans); } return 0; } /* 1 2 5 14 42 132 */