bzoj1407Noi2002savage数论
若第i个和第j个野人相聚,则有
P[ i ] * b + C[ i ] = P[ j ] * b + C[ j ] ( mod m )
m为洞的个数,移项得
( P[ i ] – P[ j ] ) * b + ( C[ j ] – C[ i ] ) * 1 == Gcd( 1 ,b )
所以可以枚举洞的个数,然后快速检验是否可行
#include <cstdio> #include <cstring> #include <cstdlib> #include <ctime> #include <cmath> #include <iostream> #include <algorithm> #include <stack> #include <deque> #include <map> #include <queue> #define max( x , y ) ( ( x ) > ( y ) ? ( x ) : ( y ) ) #define min( x , y ) ( ( x ) < ( y ) ? ( x ) : ( y ) ) #define FOR( Tmp , St , Ed ) for ( int Tmp = St ; Tmp < Ed ; Tmp ++ ) #define FORD( Tmp , St , Ed ) for ( int Tmp = St ; Tmp > Ed ; Tmp -- ) const int max_int = ( ~0U >> 1 ) , oo = ( 1e9 ) ; using namespace std ; const int Maxn = ( 150 ) , Max_Ans = ( 1e6 ) ; int N , C[ Maxn ] , P[ Maxn ] , L[ Maxn ] ; int Pab[ Maxn ][ Maxn ] , Cab[ Maxn ][ Maxn ] ; inline void Gcd( int a , int b , int &d , int &x , int &y ) { int c = a % b ; if ( c == 0 ) d = b , x = 0 , y = 1 ; else { Gcd( b , c , d , x , y ) ; int t = x ; x = y ; y = t - a / b * y ; } return ; } inline bool Check( int m ) { int a , b , d , x , y , mm ; FOR( i , 0 , N ) FOR( j , i + 1 , N ) { a = Pab[ i ][ j ] , b = Cab[ i ][ j ] ; Gcd( a , m , d , x , y ) ; if ( ( b % d ) != 0 ) continue ; b /= d , mm = m / d ; int ans = x * b ; while ( ans < 0 ) ans = ans + mm ; while ( ans >= mm ) ans = ans - mm ; if ( ans <= L[ i ] && ans <= L[ j ] ) return 0 ; } return 1 ; } int main() { freopen( "savage.in" , "r" , stdin ) , freopen( "savage.out" , "w" , stdout ) ; scanf( "%d" , &N ) ; int cnt = 0 ; FOR( i , 0 , N ) { scanf( "%d%d%d" , &C[ i ] , &P[ i ] , &L[ i ] ) ; C[ i ] -- ; cnt = max( cnt , C[ i ] ) ; } FOR( i , 0 , N ) FOR( j , i + 1 , N ) { Pab[ i ][ j ] = P[ i ] - P[ j ] ; Cab[ i ][ j ] = C[ j ] - C[ i ] ; if ( Pab[ i ][ j ] < 0 ) Pab[ i ][ j ] *= - 1 , Cab[ i ][ j ] *= - 1 ; } FOR( Ans , cnt + 1 , Max_Ans ) if ( Check( Ans ) ) { cout << Ans << endl ; break ; } return 0 ; }
数论真的太弱。。