[HNOI2012]排队
Posted on 2015年1月13日 19:31/****************************************\ * Author : ztx * Title : [HNOI2012]排队 * ALG : * CMT : 1 首先不考虑两个老师相邻的情况,即将老师看做男生, 再用隔板法得到此时的方案数为 P(n+2,n+2)*A(n+3,m)*P(m,m) 2 再找出两个老师相邻的方案数.将两个老师看做一个人, 再用隔板法得到方案数为 P(n+1,n+1)*P(2,2)*A(n+2,m)*P(m,m) 3 将两个数相减得到答案,最终化简为 ans = (n*n+3*n+2*m) * Π(1,n+1) * Π(n-m+4,n+2) * Time : \****************************************/
/****************************************\ * Author : ztx * Title : [HNOI2012]排队 * ALG : * CMT : 1 首先不考虑两个老师相邻的情况,即将老师看做男生, 再用隔板法得到此时的方案数为 P(n+2,n+2)*A(n+3,m)*P(m,m) 2 再找出两个老师相邻的方案数.将两个老师看做一个人, 再用隔板法得到方案数为 P(n+1,n+1)*P(2,2)*A(n+2,m)*P(m,m) 3 将两个数相减得到答案,最终化简为 ans = (n*n+3*n+2*m) * Π(1,n+1) * Π(n-m+4,n+2) * Time : \****************************************/ #include <cstdio> #include <cstring> typedef long long ll ; #define max(x,y) ((x)>(y)?(x):(y)) #define hpsize 10000LL #define width 10000LL struct HP { int size ; int a[hpsize] ; HP() { size = 1 ; a[1] = 0 ; } void Assign(int x) { size = 0 ; while (x) { a[++size] = x%width ; x /= width ; } } HP operator * (const int b) const { HP ret ; int i , x = 0 ; for (i = 1 ; i <= size ; i ++ ) ret.a[i] = a[i]*b ; for (ret.size = 1 ; ret.size<=size || x ; ret.size ++ ) { ret.a[ret.size] += x ; x = ret.a[ret.size]/width ; ret.a[ret.size] %= width ; } while (!ret.a[ret.size] && ret.size>1) ret.size -- ; return ret ; } void Print() { printf("%d", a[size]); for (int i = size-1 ; i > 0 ; i -- ) printf("%04d", a[i] ) ; } } ; HP ans ; int n , m , i ; int main() { #define READ #ifdef READ freopen("bzoj_2729.in" ,"r",stdin ) ; freopen("bzoj_2729.out","w",stdout) ; #endif scanf("%d%d", &n , &m ) ; if (m > n+3) { putchar('0') ; goto END ; } ans.Assign(n*n+3*n+2*m) ; for (i = 1 ; i <= n+1 ; i ++ ) ans = ans*i ; for (i = n-m+4 ; i <= n+2 ; i ++ ) ans = ans*i ; ans.Print() ; END : ; #ifdef READ fclose(stdin) ; fclose(stdout) ; #else getchar() ; getchar() ; #endif return 0 ; }