• [FJOI2016]建筑师



    题解

    首先可以发现(n)这个楼将序列分成的两半
    前一半就是让你选出(A)个数,并且以(n)为结尾,每个数到下一个数的这段区间的数一定小于这个数
    那么这可以看做是什么呢?
    是不是可以把每段区间内的数看做是一个环然后做环排列?
    最大的数就当做环首
    这就是((A-1))个环排列
    那么这就是第一类斯特林数了

    (S(n,m)=(n-1)S(n-1,m)+S(n-1,m-1))表示对于新加入的数是放入以前的环中还是新开一个环

    那么就枚举楼(n)在哪里,然后前后做环排列即可
    这样单次询问复杂度是(O(n))
    可以发现把(n)拎出来之后就剩下了(A+B-2)个环排列,把((n-1))个数排成(A+B-2)个环排列然后把任意(A-1)个弄到(n)的前面就是答案了

    代码

    #include<map> 
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int M = 50050 ;
    const int mod = 1e9 + 7 ;
    using namespace std ;
    
    inline int read() {
    	char c = getchar() ; int x = 0 , w = 1 ;
    	while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    	while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    	return x*w ;
    }
    
    int n , A , B , ans ;
    int fac[M] , inv[M] , finv[M] , s[M][205] ;
    
    inline int C(int n , int m) {
    	return 1LL * fac[n] * finv[m] % mod * finv[n - m] % mod ;
    }
    int main() {
    	fac[0] = 1 ; 
    	for(int i = 1 ; i <= 50000 ; i ++) fac[i] = 1LL * fac[i - 1] * i % mod ;
    	inv[1] = 1 ;
    	for(int i = 2 ; i <= 50000 ; i ++) inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod ;
    	finv[0] = 1 ;
    	for(int i = 1 ; i <= 50000 ; i ++) finv[i] = 1LL * finv[i - 1] * inv[i] % mod ;
    	s[0][0] = 1 ;
    	for(int i = 1 ; i <= 50000 ; i ++)
    		for(int j = 1 ; j <= min(200 , i) ; j ++)
    			s[i][j] = (s[i - 1][j - 1] + 1LL * (i - 1) * s[i - 1][j] % mod) % mod ;
    	int Case = read() ;
    	while(Case --) {
    		n = read() ; A = read() ; B = read() ; ans = 0 ;
    		printf("%d
    ",1LL * s[n - 1][A + B - 2] * C(A + B - 2 , A - 1) % mod) ;
    	}
    	return 0 ;
    }
    
  • 相关阅读:
    java面试-synchronized底层实现机制
    java面试-内存分配与回收策略
    java面试-对象的创建、内存布局、访问定位
    推荐算法-余弦相似度
    推荐算法-欧几里得距离
    MySQL总结
    MySQL事务
    MySQL-一条sql语句的执行顺序
    mysql 表格操作指令大全(Show、desc、create、insert into、delete、select、drop、update、alter)
    mysql 创建数据数据库 (避免新建的库名已经存在、设置编码)
  • 原文地址:https://www.cnblogs.com/beretty/p/10519892.html
Copyright © 2020-2023  润新知