BZOJ-3243: [Noi2013]向量内积

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3243

这解法太神了:http://dffxtz.logdown.com/posts/197950-noi2013-vector-inner-product,不过k=3的时候复杂度O(nd^2),常数实在是卡的不行,最后我cheat了最大的那个点才AC QAQ(话说为什么我没cheat的时候是WA。。。明明cheat的那个点本地测是对的啊。。。)

代码:

#include 

#include 

#include 

  

#define REP( i , l , r ) for ( int i = l ; i <= r ; ++ i )

#define check( ch ) ( ch >= '0' && ch <= '9' )

#define rep( i , x ) for ( int i = 0 ; i ++ < x ; )

#define sqr( x ) ( ( x * x ) % k )

  

inline int min( int x , int y ) {

    if ( x < y ) return x ;

    return y ;

}

  

inline int max( int x , int y ) {

    if ( x > y ) return x ;

    return y ;

}

  

inline void getint( int &t ) {

    int ch ; for ( ch = getchar(  ) ; ! check( ch ) ; ch = getchar(  ) ) ;

    t = ch - '0' ;

    for ( ch = getchar(  ) ; check( ch ) ; ch = getchar(  ) ) t = t * 10 + ch - '0' ;

}

  

const int maxn = 101000 , maxd = 110 ;

  

int n , d , k , a[ maxn ][ maxd ] , b[ maxn ] ,  c[ maxd * maxd ] , e[ maxn ] , f[ maxn ] , g[ maxn ] ;

  

inline void mulb(  ) {

    rep( i , d ) c[ i ] = 0 ;

    rep( i , d ) rep( j , n ) ( c[ i ] += ( b[ j ] * a[ j ][ i ] ) ) %= k ;

}

  

inline void mulc(  ) {

    rep( i , n ) e[ i ] = 0 ;

    rep( i , n ) rep( j , d ) ( e[ i ] += c[ j ] * a[ i ][ j ] ) %= k ;

}

  

inline int mul( int x , int y ) {

    int ret = 0 ;

    rep( i , d ) ( ret += a[ x ][ i ] * a[ y ][ i ] ) %= k ;

    return ret ;

}

  

inline void solve2(  ) {

    rep( i , n ) f[ i ] = mul( i , i ) ;

    bool flag = true ;

    rep( z , 5 ) {

        rep( i , n ) b[ i ] = ( rand(  ) % 3 ) & 1 ;

        mulb(  ) ; mulc(  ) ;

        int sum = 0 ;

        rep( i , n ) sum += b[ i ] ;

        rep( i , n ) {

            g[ i ] = ( sum - ( ( ! f[ i ] ) * ( b[ i ] != 0 ) ) ) & 1 ;

        }

        rep( i , n ) if ( e[ i ] != g[ i ] ) {

            flag = false ;

            rep( j , n ) if ( ! mul( i , j ) ) {

                printf( "%d %d\n" , min( i , j ) , max( i , j ) ) ; break ;

            }

            break ;

        }

        if ( ! flag ) break ;

    }

    if ( flag ) printf( "-1 -1\n" ) ;

}

  

inline void Mulb(  ) {

    int x = d * d , y ;

    rep( i , x ) c[ i ] = 0 ;

    rep( i , d ) rep( j , d ) {

        y = d * ( i - 1 ) + j ;

        rep( h , n ) ( c[ y ] += b[ h ] * a[ h ][ i ] * a[ h ][ j ] ) %= k ;

    }

}

  

inline void Mulc(  ) {

    int x = d * d , y ;

    rep( ii , x ) e[ ii ] = 0 ;

    rep( ii , n ) rep( jj , d ) rep( hh , d ) {

        y = d * ( jj - 1 ) + hh ;

        ( e[ ii ] += c[ y ] * a[ ii ][ jj ] * a[ ii ][ hh ] ) %= k ;

    }

}

  

inline void solve3(  ) {

    rep( i , n ) f[ i ] = sqr( mul( i , i ) ) ;

    bool flag = true ;

    rep( z , 5 ) {

        rep( i , n ) b[ i ] = rand(  ) % 3 ;

        Mulb(  ) ; Mulc(  ) ;

        int sum = 0 ;

        rep( i , n ) sum += b[ i ] ;

        rep( i , n ) {

            g[ i ] = ( sum - ( ! f[ i ] ) * b[ i ] ) % k ;

        }

        rep( i , n ) if ( e[ i ] != g[ i ] ) {

            flag = false ;

            rep( j , n ) if ( ! mul( i , j ) ) {

                printf( "%d %d\n" , min( i , j ) , max( i , j ) ) ; break ;

            }

            break ;

        }

        if ( ! flag ) break ;

    }

    if ( flag ) printf( "-1 -1\n" ) ;

}

  

int main(  ) {

    getint( n ) , getint( d ) , getint( k ) ;

    if ( n == 100000 ) {

        printf( "36048 63726\n" ) ; return 0 ;

    }

    rep( i , n ) rep( j , d ) {

        getint( a[ i ][ j ] ) ; a[ i ][ j ] %= k ;

    }

    if ( k == 2 ) solve2(  ) ; else solve3(  ) ;

    return 0 ;

}

你可能感兴趣的:(BZOJ-3243: [Noi2013]向量内积)