zoukankan      html  css  js  c++  java
  • P4609 [FJOI2016]建筑师 第一类斯特林数

    题意:

    戳这里

    分析:

    枚举一下 (n) 的位置,分成左右两段,然后将每一个能看见的建筑物和它会挡住的建筑物分成一组,然后每一组内部就是一个圆排列,因为默认最大的那个建筑是分割点,所以每一组内部就是一个圆排列

    按照第一类斯特林数的递推公式 (s[i][j]=s[i-1][j-1]+(i-1)*s[i-1][j])

    这就是每一个圆排列的方案数之和,然后我们从这 (a+b-2) 个圆排列选出 (a-1) 个放在左边,也就是再乘上一个组合数

    (ans=s[n-1][a+b-2]*C(a+b-2,a-1))

    复杂度 (O(n^2))

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
        int read()
        {
            int x=0,f=1;char ch=getchar();
            while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
            while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
            return x*f;
        }
    
        const int maxn = 5e4+5;
        const int maxs = 205;
        const int mod = 1e9+7;
        long long s[maxn][maxs],fac[maxn],inv[maxn];
        int t,n,a,b;
    
        void init()
        {
            fac[0]=fac[1]=inv[0]=inv[1]=1;
    		s[0][0]=s[1][1]=1;
            for(int i=2;i<=50000;i++)
            {
                fac[i]=fac[i-1]*i%mod;
                inv[i]=inv[mod%i]*(mod-mod/i)%mod;
                for(int j=1;j<=min(i,200);j++) s[i][j]=(s[i-1][j-1]+s[i-1][j]*(i-1))%mod;
            }
            for(int i=1;i<=50000;i++) inv[i]=inv[i]*inv[i-1]%mod;
        }
    
        long long C(int n,int m)
        {
            return fac[n]*inv[n-m]%mod*inv[m]%mod;
        }
    
        void work()
        {
            init();
            t=read();
            while(t--)
            {
                n=read();a=read();b=read();
                printf("%lld
    ",s[n-1][a+b-2]*C(a+b-2,a-1)%mod);
            }
        }
    
    }
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    单片机触摸屏校准
    C中的预编译宏定义
    Android之网络摄像头
    曾经的UCOSii
    关于ST-Link下载STM32程序的使用
    关于IAR开发STM32配置
    学习C#(一)
    ESP8266使用详解--基于Lua脚本语言
    (五)Lua脚本语言入门
    (四)Lua脚本语言入门(数组遍历)
  • 原文地址:https://www.cnblogs.com/youth518/p/14219503.html
Copyright © 2011-2022 走看看