题目:
http://www.lydsy.com/JudgeOnline/problem.php?id=1853
http://www.lydsy.com/JudgeOnline/problem.php?id=2393
两道都是裸的容斥原理,注意一下细节不要爆long long,然后除去多余的倍数,按照从大到小排序可以使速度变得更快。
代码:
1853: [Scoi2010]幸运数字:
#include
#include
#include
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
#include
#include
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 ;
}