BZOJ4602: [Sdoi2016]齿轮 DFS 逆元

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ; 
}

 

                                                                                                                                 

以上是关于BZOJ4602: [Sdoi2016]齿轮 DFS 逆元的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj4602--Sdoi2016齿轮

bzoj 4602: [Sdoi2016]齿轮

BZOJ4602: [Sdoi2016]齿轮 DFS 逆元

bzoj 4602: [Sdoi2016]齿轮

4602: [Sdoi2016]齿轮

[Sdoi2016]齿轮