• Wannafly挑战赛9 D


    链接:https://www.nowcoder.com/acm/contest/71/D
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制: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
    ");
          continue;
        }
        LL A = work(m, k);
        LL B = work(n + k + 1 - m, k + 1);
        LL ans = A * B % p;
        printf("%lld
    ", ans);
      }
      return 0;
    }
    /*
     
     A:
     ---+-----------------------------------
     mk|   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
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   1
     2  |
     3  |
     4  |
     5  |
     6  |
     7  |
     
     n = 2
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   2
     2  |   1    1
     3  |
     4  |
     5  |
     6  |
     7  |
     
     n = 3
     ---+-----------------------------------
     mk|   1    2    3    4    5    6    7
     ---+-----------------------------------
     1  |   5
     2  |   2    3
     3  |   1    1    1
     4  |
     5  |
     6  |
     7  |
     
     n = 4
     ---+-----------------------------------
     mk|   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
     ---+-----------------------------------
     mk|   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  |
     
     */
    
  • 相关阅读:
    surfaceView和Camera配合进行摄像头的预览
    Android中SurfaceView的使用详解
    Java 图片与byte数组互相转换
    Android的GridView和Gallery结合Demo
    AlertDialog dismiss 和 cancel方法的区别
    HttpClient4.0
    IntentFilter
    ViewPagerindicator 源码解析
    android背景平铺方式 tileMode
    android requestWindowFeature使用详解
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8408726.html
Copyright © 2020-2023  润新知