HNOI2017 抛硬币

来源:互联网 发布:淘宝手机端复制链接 编辑:程序博客网 时间:2024/05/16 08:09

题解

实际上就是要求a+bi=b+1Cia+b,组合数取模即可。
直接算显然会超时,考虑优化。注意到ni=0Cin=2n,而且Cin是对称的。所以对于a+b为奇数的情况,直接用2a+b/2=2a+b1计算出ni=a+b2Cia+b,剩下a+b2i=b+1Cia+b可以直接暴力计算。
对于a+b为偶数的情况,需要特殊处理一下中间的边界。

SRC

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 100 + 10#define M 2000000 + 10typedef long long ll ;ll Tab[N] , f[2][M] ;ll a , b , k , MO ;int P = 1e9 ;int ans ;ll Power( ll x , ll k , int MO ) {    ll s = 1 ;    while ( k ) {        if ( k & 1 ) s = s * x % MO ;        x = x * x % MO ;        k /= 2 ;    }    return s ;}ll Count( ll n , int p ) { return n == 0 ? 0 : n / p + Count( n / p , p ) ; }ll fac( ll n , int p ) {    if ( n == 0 ) return 1 ;    ll ret = 1 ;    int t = p == 2 ? 0 : 1 ;    if ( n >= MO ) ret = f[t][MO] ;    ret = Power( ret , n / MO , MO ) ;    ret = ret * f[t][n%MO] % MO ;    return ret * fac( n / p , p ) % MO ;}ll phi( ll p , ll pk ) { return pk / p * (p - 1) ; }ll Calc( ll n , ll m ) {    ll ret = 1 ;    MO = Power( 2 , 9 , P ) ;    ll k = Count( n , 2 ) - Count( m , 2 ) - Count( n - m , 2 ) ;    ll a1 = 0 ;    if ( k < 9 ) a1 = Power( 2 , k , MO ) * fac( n , 2 ) % MO * Power( fac( m , 2 ) * fac( n - m , 2 ) % MO , phi( 2 , MO ) - 1 , MO ) % MO ;    ret = (P / MO) * Power( P / MO , phi( 2 , MO ) - 1 , MO ) % P * a1 % P ;    MO = Power( 5 , 9 , P ) ;    k = Count( n , 5 ) - Count( m , 5 ) - Count( n - m , 5 ) ;    ll a2 = 0 ;    if ( k < 9 ) a2 = Power( 5 , k , MO ) * fac( n , 5 ) % MO * Power( fac( m , 5 ) * fac( n - m , 5 ) % MO , phi( 5 , MO ) - 1 , MO ) % MO ;    ret = (ret + (P / MO) * Power( P / MO , phi( 5 , MO ) - 1 , MO ) % P * a2 % P) % P ;    return ret ;}ll Calc2( ll n , ll m ) {    ll ret = 1 ;    MO = Power( 2 , 9 , P ) ;    ll k = Count( n , 2 ) - Count( m , 2 ) - Count( n - m , 2 ) - 1 ;    ll a1 = 0 ;    if ( k < 9 ) a1 = Power( 2 , k , MO ) * fac( n , 2 ) % MO * Power( fac( m , 2 ) * fac( n - m , 2 ) % MO , phi( 2 , MO ) - 1 , MO ) % MO ;    ret = (P / MO) * Power( P / MO , phi( 2 , MO ) - 1 , MO ) % P * a1 % P ;    MO = Power( 5 , 9 , P ) ;    k = Count( n , 5 ) - Count( m , 5 ) - Count( n - m , 5 ) ;    ll a2 = 0 ;    if ( k < 9 ) a2 = Power( 5 , k , MO ) * fac( n , 5 ) % MO * Power( fac( m , 5 ) * fac( n - m , 5 ) % MO , phi( 5 , MO ) - 1 , MO ) % MO ;    a2 = a2 * Power( 2 , phi( 5 , MO ) - 1 , MO ) % MO ;    ret = (ret + (P / MO) * Power( P / MO , phi( 5 , MO ) - 1 , MO ) % P * a2 % P) % P ;    return ret ;}int main() {    freopen( "coin.in" , "r" , stdin ) ;    freopen( "coin.out" , "w" , stdout ) ;    Tab[0] = 1 ;    for (int i = 1 ; i <= 9 ; i ++ ) Tab[i] = Tab[i-1] * 10 ;    f[0][0] = f[1][0] = 1 ;    int UP = Power( 2 , 9 , P ) ;    for (int i = 1 ; i <= UP ; i ++ ) {        f[0][i] = f[0][i-1] ;        if ( i & 1 ) f[0][i] = f[0][i] * i % UP ;    }    UP = Power( 5 , 9 , P ) ;    for (int i = 1 ; i <= UP ; i ++ ) {        f[1][i] = f[1][i-1] ;        if ( i % 5 ) f[1][i] = f[1][i] * i % UP ;    }    while ( scanf( "%lld%lld%lld" , &a , &b , &k ) != EOF ) {        ans = Power( 2 , a + b - 1 , P ) ;        if ( (a + b) & 1 ) {            for (ll i = b + 1 ; i <= (a + b) / 2 ; i ++ ) ans = (ans + Calc( a + b , i )) % P ;        } else {            ans = ((ans - Calc2( a + b , (a + b) / 2 )) % P + P) % P ;            for (ll i = b + 1 ; i <= (a + b) / 2 ; i ++ ) ans = (ans + Calc( a + b , i )) % P ;        }        ans %= Tab[k] ;        if ( k == 1 ) printf( "%d\n" , ans ) ;        if ( k == 2 ) printf( "%02d\n" , ans ) ;        if ( k == 3 ) printf( "%03d\n" , ans ) ;        if ( k == 4 ) printf( "%04d\n" , ans ) ;        if ( k == 5 ) printf( "%05d\n" , ans ) ;        if ( k == 6 ) printf( "%06d\n" , ans ) ;        if ( k == 7 ) printf( "%07d\n" , ans ) ;        if ( k == 8 ) printf( "%08d\n" , ans ) ;        if ( k == 9 ) printf( "%09d\n" , ans ) ;    }    return 0 ;}

以上.

1 0
原创粉丝点击