BZOJ-1853: [Scoi2010]幸运数字 && 2393: Cirno的完美算数教室(容斥原理)

题目:

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 ; 
}
    原文作者:AmadeusChan
    原文地址: https://www.jianshu.com/p/be462bfe80c5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞