BZOJ-2729: [HNOI2012]排队(排列组合+高精度乘法)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2729

裸的排列组合,用插空法,先加男生,再加老师,再加女生,易得答案:

Ans( n , m ) = A( n , n ) [ A( 2 , n + 1 ) A( m , n + 3 ) + A( 1 , n + 1 ) A( 2 , 2 ) A( 1 , m ) A( m - 1 , n + 2 ) ]

化简:

Ans( n , m ) = n! ( n + 1 ) [ ( n - m + 4 ) ( n - m + 5 ) ... ( n + 2 ) ] [ ( n + 3 ) n + 2 m ]

然后就用高精度乘法算就可以啦~

代码:


838ba61ea8d3fd1f3774ac59324e251f95ca5f57.jpg.png

压了4位,速度还是这么慢。。。话说那些100+ms是怎么达到的?难道都是敲了FFT!!!?

#include 

#include 
#include 
 
using namespace std ;
 
#define MAXN 3010
#define MAX 10000
 
struct BigNumber {
     
    int a[ MAXN ] , m ;
     
    void Transform( int t ) {
        m = 0 ;
        if ( ! t ) {
            a[ m = 1 ] = 0 ;
        } else {
            for ( ; t ; t /= MAX ) a[ ++ m ] = t % MAX ;
        }
    }
     
    void Print(  ) {
        for ( int i = m ; i ; i -- ) {
            if ( i != m ) {
                if ( a[ i ] < 1000 ) printf( "0" ) ;
                if ( a[ i ] < 100 ) printf( "0" ) ;
                if ( a[ i ] < 10) printf( "0" ) ;
            }
            printf( "%d" , a[ i ] ) ;
        }
        printf( "\n" ) ;
    }
     
} ans , rec ;
 
int n , m ;
 
BigNumber Multiply( BigNumber x , BigNumber y ) {
    BigNumber ret ; ret.m = 0 ;
    memset( ret.a , 0 , sizeof( ret.a ) ) ;
    for ( int i = 0 ; i ++ < x.m ; ) {
        for ( int j = 0 ; j ++ < y.m ; ) {
            ret.a[ i + j - 1 ] += x.a[ i ] * y.a[ j ] ;
            ret.m = max( ret.m , i + j - 1 ) ;
            for ( int k = i + j - 1 ; ret.a[ k ] >= MAX ; k ++ ) {
                ret.a[ k + 1 ] += ret.a[ k ] / MAX ;
                ret.a[ k ] %= MAX ;
                ret.m = max( ret.m , k + 1 ) ;
            }
        }
    }
    return ret ;
}
 
int main(  ) {
    scanf( "%d%d" , &n , &m ) ;
    ans.Transform( 1 ) ;
    for ( int i = 0 ; i ++ < n ; ) {
        rec.Transform( i ) ;
        ans = Multiply( ans , rec ) ;
    }
    rec.Transform( n + 1 ) ;
    ans = Multiply( ans , rec ) ;
    for ( int i = n - m + 4 ; i <= n + 2 ; i ++ ) {
        rec.Transform( i ) ;
        ans = Multiply( ans , rec ) ;
    }
    rec.Transform( ( n + 3 ) * n + 2 * m ) ;
    ans = Multiply( ans , rec ) ;
    ans.Print(  ) ;
    return 0 ;
}

你可能感兴趣的:(BZOJ-2729: [HNOI2012]排队(排列组合+高精度乘法))