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 ;
}
时间: 2024-10-01 07:02:19

BZOJ4602: [Sdoi2016]齿轮 DFS 逆元的相关文章

[bzoj4602] [Sdoi2016]齿轮

记忆化搜索,强行double可过...数据简直.. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #define ld double 7 using namespace std; 8 const int maxn=1023,maxm=10023; 9 const ld eps=1e-8; 10

4602: [Sdoi2016]齿轮

4602: [Sdoi2016]齿轮 Description 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x : y.即如果只考虑这两个组合齿轮,编号为u的齿轮转动x圈,编号为v的齿轮会转动y圈.传动比为正表示若编号 为u的齿轮顺时针转动,则编号为v的齿轮也顺时针转动.传动比为负表示若编号为u的齿轮顺时针转动,则编号为v 的齿轮会逆时针转动.若不同链条的传动比不相容,则有些齿轮无法转动.我们希望知道,系统中的这N个组合齿 轮能否同时转动.

[Sdoi2016]齿轮

4602: [Sdoi2016]齿轮 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 613  Solved: 324 [Submit][Status][Discuss] Description 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x : y.即如果只考虑这两个组合齿轮,编号为u的齿轮转动x圈,编号为v的齿轮会转动y圈.传动比为正表示若编号 为u的齿轮顺时针转动,则编号为v的齿轮也

【bzoj4602】[Sdoi2016]齿轮

dfs,连边,边权为比值,赋值搜索,遇到矛盾时退出 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef long long LL; typedef double DB; #define eps 1e-8 #defin

bzoj 4602: [Sdoi2016]齿轮

传送门 题解: 一个简单的dfs或并查集即可搞定. dfs做法:建出图来以后,由一个节点跑一遍,如果儿子节点没有被遍历过,dfs此节点,否则,判断他俩的比例与他俩到根节点的比例之比是否相等. 对于判断两节点的比例,double可以安全存下. 我怕炸精度(其实不会,感觉自己跟个zz一样),于是想不用double,用个pair存下分子分母.后来觉得导起来太麻烦,于是用逆元求(越来越傻了). 逆元不需要太大的素数,大了会T,小了会WA. bzoj上测试了5个素数:1000000007,66191,73

待 题表

题表 达哥终极杂题表Bzoj2839 hdu6021 Codeforces 804DBzoj2248 hdu5575 Codeforces 786CBzoj2013 bzoj2676 Codeforces 803CBzoj2386 bzoj3782 Codeforces 813DBzoj2699 cogs1667 Codeforces 814DBzoj4798 bzoj2064 Codeforces 814EBzoj4639 bzoj3505 Codeforces 815ABzoj4417 bz

联赛之前的题表(已完成)汇总(可能有遗漏)

联赛之前的搞搞(其实是懒得分类) 博弈论 poj3537 poj1704 hdu5996两个插头 HDU1693 Eat the Trees COGS1283. [HNOI2004] 邮递员kdtree板子1941: [Sdoi2010]Hide and Seek旋转卡壳 pj2187凸包 cogs896 bzoj2829 信用卡凸包莫比乌斯反演基础 bzoj 4173 zhao gui lv bzoj 3529 mobiwus bzoj 4407 mobiwus bzoj 2818 mobiw

[qbzt寒假] 并查集

并查集: \(Kruscal\),\(Tarjan\)求\(LCA\) 分类并查集:食物链,团伙(敌人的敌人是我的朋友) 带权并查集:\(SDOI2016\)齿轮(可用 int father(int x) { return fa[x]==x?x:fa[x]=father(f[x]); } Luogu3101 滑雪等级[] 建边:任意相邻两格子之间建边,权值为海拔差 将边排序,从小往大一个一个往里加,当一个并查集内部有起点,并且大小(点数)>=T,这里面所有的起点的D=最后加入的边 #includ

BZOJ 4517: [Sdoi2016]排列计数 错排+逆元

4517: [Sdoi2016]排列计数 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. T=500000,n≤1000000,m≤1000000 Output 输出 T 行,每行一个数,表示