HDU - 4372 Count the Buildings 【stirling数】

Count the Buildings

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3026    Accepted Submission(s): 1000


 

Problem Description

There are N buildings standing in a straight line in the City, numbered from 1 to N. The heights of all the buildings are distinct and between 1 and N. You can see F buildings when you standing in front of the first building and looking forward, and B buildings when you are behind the last building and looking backward. A building can be seen if the building is higher than any building between you and it.
Now, given N, F, B, your task is to figure out how many ways all the buildings can be.

 

Input

First line of the input is a single integer T (T<=100000), indicating there are T test cases followed.
Next T lines, each line consists of three integer N, F, B, (0<N, F, B<=2000) described above.

 

Output

For each case, you should output the number of ways mod 1000000007(1e9+7).

 

Sample Input

 

2 3 2 2 3 2 1

 

Sample Output

 

2 1

 

Source

2012 Multi-University Training Contest 8

 

Recommend

zhuyuanchen520

题意:N个房子,高度为1到N。从左边看能看到F个,右边能看到B个,求满足此条件的方案数。

分析:最高的房子两边一定都能看到,那么左边剩F-1个,这F-1个一定是升序排列,右边剩B-1个,降序排列,总共为F+B-2个,

可以将剩下的N-1个数分为F+B-2个组,其中每组的高度为该组中最高的,剩余的排列在这个右边(从左边看)或左面(从右边看),通过stirling数来解决。

第一类Stirling数表示将 n 个不同元素构成m个圆排列的数目。

递推式满足s(n,m)=s(n-1,m-1)+(n-1)*s(n-1,m)

最后ans=s(n-1,f+b-2)*C_{f+b-2}^{f-1}

代码乱写,重要的是思路

//#include <bits/stdc++.h>
#include "cstdio"
#include "cstring"
#include "iostream"
using namespace std;
const int mod = 1e9+7;
long long inv[2004];
long long fac[2004];
long long s[2004][2004];
long long qk(long long a,long long n)
{
    long long ans=1;
    while(n)
    {
        if(n&1)ans=a*ans%mod;
        n>>=1;
        a=a*a%mod;
    }
    return ans;
}
long long c(long long a,long long b)
{
    if(a==b)return 1;
    if(a<b)return 0;
    return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
long long dfs(long long n,long long m)
{
    if(n<m)return 0;
    if(n==m)return 1;
    if(m==0)return 0;
    if(s[n][m]!=0)return s[n][m];
    else {
        s[n][m]=(dfs(n-1,m-1)+(n-1)*dfs((n-1),m)%mod)%mod;
        return s[n][m];
    }
}
void init()
{
    memset(s,0, sizeof(s));
    s[1][1]=1;
    fac[0]=fac[1]=1;
    for(int i=2;i<=2000;i++)
        fac[i]=fac[i-1]*i%mod;
    inv[2000]=qk(fac[2000],mod-2);
    for(int i=2000-1;i>=0;i--)
        inv[i]=inv[i+1]*(i+1)%mod;
}
int main () {
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,f,b;
        cin>>n>>f>>b;
        printf("%lld\n",dfs(n-1,f+b-2)*c(f+b-2,f-1)%mod);
    }

}

猜你喜欢

转载自blog.csdn.net/qq_42671946/article/details/85100892