Wannafly挑战赛9 D - 造一造
链接:https://www.nowcoder.com/acm/contest/71/D
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
WYF正试图用一个栈来构造一棵树,现在他已经构造了n个元素作为树的节点,只要将这n个元素依次入栈出栈就可以形成一棵树了。当然,这个问题与树并没有关系,所以它叫做WYF的栈。每次你可以入栈一个新元素或者当栈非空时出栈一个元素,n个元素必须依次入栈,而WYF希望其中第m个元素入栈之后,栈中恰好有k个元素,现在他想知道一共有多少种入栈出栈顺序满足这个条件。
输入描述:
第一行一个正整数T,表示数据组数。(1<=T<=10000)
对于每组数据包含一行三个正整数n,m,k。
输出描述:
对于每组数据输出一个正整数表示答案。
由于答案可能过大,所以只需要输出对109+7取模后的答案
示例1
输入
2 3 3 3 3 3 2
输出
1 2
示例2
输入
5 10 3 2 10 2 2 10 7 5 10 6 2 10 7 6
输出
6864 11934 2200 3780 924
示例3
输入
2 5 4 4 5 2 1
输出
5 14
备注:
1<=n,m,k<=10^6
题解
找规律。
可以把过程分成两个阶段,答案是两个阶段的方案数乘积。
第一阶段:压入第$m$个元素时,刚好有$k$个元素在栈中,这样的状态停止的方案数记为$A$,显然$A$只和$m$和$k$有关,和$n$无关。
第二阶段:有$k$个元素在栈中,还剩$n-m$个元素未压入,将栈弹空为止的方案数记为$B$。
写个暴力可以发现两个阶段的方案数存在同一套规律,可以看代码中最后的注释部分。
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL p = 1e9 + 7; const int maxn = 3e6 + 10; LL f[maxn]; //****************************** //返回d=gcd(a,b);和对应于等式ax+by=d中的x,y long long extend_gcd(long long a,long long b,long long &x,long long &y) { if(a==0&&b==0) return -1;//无最大公约数 if(b==0){x=1;y=0;return a;} long long d=extend_gcd(b,a%b,y,x); y-=a/b*x; return d; } //*********求逆元素******************* //ax = 1(mod n) long long mod_reverse(long long a,long long n) { long long x,y; long long d=extend_gcd(a,n,x,y); if(d==1) return (x%n+n)%n; else return -1; } LL C(LL n, LL m) { long long A = f[n]; long long B = f[n - m] * f[m] % p; long long C = mod_reverse(B, p); return A * C % p; } LL work(LL n, LL m) { if(n == m) return 1; return (C(n * 2 - m - 1, n - m) - C(n * 2 - m - 1, n - m - 1) + p) % p; } int main() { f[0] = 1; for(long long i = 1; i < maxn; i ++) { f[i] = (f[i - 1] * i) % p; } int T; scanf("%d", &T); while(T --) { LL n, m, k; scanf("%lld%lld%lld", &n, &m, &k); if(m > n || m < k) { printf("0\n"); continue; } LL A = work(m, k); LL B = work(n + k + 1 - m, k + 1); LL ans = A * B % p; printf("%lld\n", ans); } return 0; } /* A: ---+----------------------------------- m\k| 1 2 3 4 5 6 7 ---+----------------------------------- 1 | 1 2 | 1 1 3 | 2 2 1 4 | 5 5 3 1 5 | 14 14 9 4 1 6 | 42 42 28 14 5 1 7 | 132 132 90 48 20 6 1 B: n = 1 ---+----------------------------------- m\k| 1 2 3 4 5 6 7 ---+----------------------------------- 1 | 1 2 | 3 | 4 | 5 | 6 | 7 | n = 2 ---+----------------------------------- m\k| 1 2 3 4 5 6 7 ---+----------------------------------- 1 | 2 2 | 1 1 3 | 4 | 5 | 6 | 7 | n = 3 ---+----------------------------------- m\k| 1 2 3 4 5 6 7 ---+----------------------------------- 1 | 5 2 | 2 3 3 | 1 1 1 4 | 5 | 6 | 7 | n = 4 ---+----------------------------------- m\k| 1 2 3 4 5 6 7 ---+----------------------------------- 1 | 14 2 | 5 9 3 | 2 3 4 4 | 1 1 1 1 5 | 6 | 7 | n = 5 ---+----------------------------------- m\k| 1 2 3 4 5 6 7 ---+----------------------------------- 1 | 42 2 | 14 28 3 | 5 9 14 4 | 2 3 4 5 5 | 1 1 1 1 1 6 | 7 | */