BZOJ-1853: [Scoi2010]幸运数字 &&

作者: AmadeusChan | 来源:发表于2018-11-29 11:10 被阅读1次

    题目:

    http://www.lydsy.com/JudgeOnline/problem.php?id=1853

    http://www.lydsy.com/JudgeOnline/problem.php?id=2393

    两道都是裸的容斥原理,注意一下细节不要爆long long,然后除去多余的倍数,按照从大到小排序可以使速度变得更快。

    代码:

    1853: [Scoi2010]幸运数字:

    #include <iostream>
    
    #include <algorithm>
    #include <cstring>
     
    using namespace std ;
     
    #define rep( i , x , y ) for ( int i = x ; i <= y ; ++ i )
     
    typedef long long ll ;
     
    const int maxn = 5010 ;
     
    ll a , b , num[ maxn ] ;
    int cnt = 0 ; 
     
    void make( ll now ) {
        if ( now > b ) return ; 
        num[ ++ cnt ] = now ;
        make( now * 10 + 6 ) , make( now * 10 + 8 ) ;
    }
     
    ll ans , n[ maxn ] ;
    int m = 0 ; 
     
    ll X ;
     
    ll gcd( ll x , ll y ) {
        if ( x < y ) swap( x , y ) ;
        ll k ;
        while ( y ) {
            k = y ;
            y = x % y ;
            x = k ;
        }
        return x ;
    }
     
    void dfs( int pos , int times , ll rec ) {
        if ( ! pos ) {
            if ( ! times ) return ;
            ll ret = ( b / rec ) - ( a / rec ) ;
            if ( times & 1 ) ans += ret ; else ans -= ret ;
            return ; 
        }
        ll temp = gcd( rec , n[ pos ] ) ;
        if ( rec / temp <= b / n[ pos ] ) dfs( pos - 1 , times + 1 , rec / temp * n[ pos ] ) ;
        dfs( pos - 1 , times , rec ) ;
    }
     
    int main(  ) {
        cin >> a >> b ; 
        make( 6 ) , make( 8 ) ;
        rep( i , 1 , cnt ) if ( num[ i ] ) {
            rep( j , 1 , cnt ) if ( i != j && ! ( num[ j ] % num[ i ] ) ) {
                num[ j ] = 0 ;
            }
        }
        memset( n , 0 , sizeof( n ) ) ;
        rep( i , 1 , cnt ) if ( num[ i ] ) {
            n[ ++ m ] = num[ i ] ;
        }
        sort( n + 1 , n + m + 1 ) ;
        -- a ;
        ans = 0 ;
        dfs( m , 0 , 1 ) ;
        cout << ans << endl ;
        return 0 ; 
    }
    

    2393: Cirno的完美算数教室:

    #include <iostream>
    #include <algorithm>
    #include <cstring>
     
    using namespace std ;
     
    #define rep( i , x , y ) for ( int i = x ; i <= y ; ++ i )
     
    typedef long long ll ;
     
    const int maxn = 5010 ;
     
    ll a , b , num[ maxn ] ;
    int cnt = 0 ; 
     
    void make( ll now ) {
        if ( now > b ) return ; 
        num[ ++ cnt ] = now ;
        make( now * 10 + 2 ) , make( now * 10 + 9 ) ;
    }
     
    ll ans , n[ maxn ] ;
    int m = 0 ; 
     
    ll X ;
     
    ll gcd( ll x , ll y ) {
        if ( x < y ) swap( x , y ) ;
        ll k ;
        while ( y ) {
            k = y ;
            y = x % y ;
            x = k ;
        }
        return x ;
    }
     
    void dfs( int pos , int times , ll rec ) {
        if ( ! pos ) {
            if ( ! times ) return ;
            ll ret = ( b / rec ) - ( a / rec ) ;
            if ( times & 1 ) ans += ret ; else ans -= ret ;
            return ; 
        }
        ll temp = gcd( rec , n[ pos ] ) ;
        if ( rec / temp <= b / n[ pos ] ) dfs( pos - 1 , times + 1 , rec / temp * n[ pos ] ) ;
        dfs( pos - 1 , times , rec ) ;
    }
     
    int main(  ) {
        cin >> a >> b ; 
        make( 2 ) , make( 9 ) ;
        rep( i , 1 , cnt ) if ( num[ i ] ) {
            rep( j , 1 , cnt ) if ( i != j && ! ( num[ j ] % num[ i ] ) ) {
                num[ j ] = 0 ;
            }
        }
        memset( n , 0 , sizeof( n ) ) ;
        rep( i , 1 , cnt ) if ( num[ i ] ) {
            n[ ++ m ] = num[ i ] ;
        }
        sort( n + 1 , n + m + 1 ) ;
        -- a ;
        ans = 0 ;
        dfs( m , 0 , 1 ) ;
        cout << ans << endl ;
        return 0 ; 
    }
    

    相关文章

      网友评论

        本文标题:BZOJ-1853: [Scoi2010]幸运数字 &&

        本文链接:https://www.haomeiwen.com/subject/cnmxcqtx.html