zoukankan      html  css  js  c++  java
  • BZOJ4602: [Sdoi2016]齿轮 DFS 逆元

    这道题就是一个DFS,有一篇奶牛题几乎一样。但是这道题卡精度。

    这道题网上的另一篇题解是有问题的。取对数这种方法可以被轻松卡。比如1e18 与 (1e9-1)*(1e9+1)取对数根本无法保证不被卡精度。所以我们需要换一个方法。

    我们取一个大质数,在这个质数的模意义下进行运算:乘法是乘法,除法变成乘逆元,负数加一个质数。这种方法虽然可能冲突,但是与数据无关。

    #include<cstdio>
    using namespace std ; 
    
    struct edge {
        int p ;
        int a ;
        int b ; 
        edge * next ; 
    } ; 
    
    const int p = 10079 ;
    
    int pow ( int a , int n ) {
        int ans = 1 ;
        while ( n ) {
            if ( n & 1 ) ans *= a , ans %= p ; 
            a *= a ; a %= p ;
            n /= 2 ;
        }
        return ans ; 
    }
    
    int inv ( const int a ) { 
        return pow ( a , p - 2 ) ; 
    } 
    
    const int MAXN = 1234 ; 
    const int MAXM = 12345 ; 
    int N , M ; 
    edge E [ MAXM * 2 ] ; 
    edge * V [ MAXN ] ;
    bool vis [ MAXN ] ;
    int dis [ MAXN ] ;
    
    void read () {
        scanf ( "%d%d" , & N , & M ) ;     
        for ( int i = 1 ; i <= N ; ++ i ) vis [ i ] = V [ i ] = 0 ;
        while ( M -- ) {
            int s , t , a , b ;
            scanf ( "%d%d%d%d" , & s , & t , & a , & b ) ;
            edge * const t1= & E [ M * 2 ] ;
            t1 -> p = t ; 
            t1 -> a = a ; 
            t1-> b = b < 0 ? b + p : b ;
            t1-> next = V [ s ] ; 
            V [ s ] = t1 ;
            edge * const f = & E [ M * 2 + 1 ] ;
            f -> p = s ; 
            f -> a = b < 0 ? b + p : b ; 
            f -> b = a ;
            f -> next = V [ t ] ; 
            V [ t ] = f ;
        }
    }
    
    bool dfs ( const int o ) { 
        vis [ o ] = true ;
        for ( edge * v = V [ o ] ; v ; v = v -> next ) 
        if ( ! vis [ v -> p ] ) {
            dis [ v -> p ] = dis [ o ] * v -> a % p * inv ( v -> b ) % p ;
            if ( ! dfs ( v -> p ) ) return false ; 
        } else 
        if ( dis [ v -> p ] != dis [ o ] * v -> a % p * inv ( v -> b ) % p ) 
            return false ;
        return true ;
    }
    
    bool solve () {
        for ( int i = 1 ; i <= N ; ++ i ) 
        if ( ! vis [ i ] && ( dis [ i ] = 1 , ! dfs ( i ) ) ) return false ; 
        return true ;
    }
    
    int main () {
        int T ; 
        scanf ( "%d" , & T ) ; 
        for ( int i = 1 ; i <= T ; ++ i ) {
            read () ; 
            printf ( "Case #%d: " , i ) ; 
            puts ( solve () ? "Yes" : "No" ) ;
        }
        return 0 ; 
    }

                                                                                                                                     

  • 相关阅读:
    [AH2017/HNOI2017]礼物
    [八省联考2018]林克卡特树lct
    [洛谷P4847]银河英雄传说V2
    [洛谷P4999]烦人的数学作业
    [洛谷P4171][JSOI2010]满汉全席
    [CF785E]Anton and Permutation
    [洛谷P2511][HAOI2008]木棍分割
    [洛谷P4430]小猴打架
    [UVA307]小木棍 Sticks
    [LOJ #6433]「PKUSC2018」最大前缀和
  • 原文地址:https://www.cnblogs.com/Christopher-Cao/p/5518896.html
Copyright © 2011-2022 走看看