• BZOJ1407: [Noi2002]Savage exgcd


    Description

    Input

    第1行为一个整数N(1<=N<=15),即野人的数目。
    第2行到第N+1每行为三个整数Ci, Pi, Li表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。
    (1<=Ci,Pi<=100, 0<=Li<=10^6 )

    Output

    仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于10^6。

    Sample Input

    3
    1 3 4
    2 7 3
    3 2 1

    Sample Output

    6
    //该样例对应于题目描述中的例子。

    Solution

    对我来说很清奇的一个思路:枚举答案。我自己推了一下式子可以推出来exgcd,但是就是想不到枚举那个m,还是要多读题..

    式子其实不难推

    求对于最小的m ,满足

    $$c_1+(p_1*x)space modspace m = c_2 + (p_2*x)space mod space m $$

    的同时,满足$x>min(l_1,l_2)$

    上式可化为:

    $$p_1*xspace modspace m -p_2*xspace modspace m=c2-c1 $$

    $$x*(p_1-p_2)-ym=c2-c1$$

    对于x,满足$x>min(l1,l2)$

    所以就化为了exgcd的标准形式,记得把x弄成最小整数解就好。

    #include <bits/stdc++.h>
    
    #define ll long long
    #define inf 0x3f3f3f3f
    #define il inline
    
    namespace io {
    
        #define in(a) a=read()
        #define out(a) write(a)
        #define outn(a) out(a),putchar('
    ')
    
        #define I_int int
        inline I_int read() {
            I_int x = 0 , f = 1 ; char c = getchar() ;
            while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
            while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
            return x * f ;
        }
        char F[ 200 ] ;
        inline void write( I_int x ) {
            if( x == 0 ) { putchar( '0' ) ; return ; }
            I_int tmp = x > 0 ? x : -x ;
            if( x < 0 ) putchar( '-' ) ;
            int cnt = 0 ;
            while( tmp > 0 ) {
                F[ cnt ++ ] = tmp % 10 + '0' ;
                tmp /= 10 ;
            }
            while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
        }
        #undef I_int
    
    }
    using namespace io ;
    
    #define N 100010
    
    int n , mod , c[N] , p[N] , l[N] ;
    
    int x , y ;
    int exgcd(int a , int b) {
        if(b == 0) {x = 1 , y = 0 ; return a;}
        int ans = exgcd(b , a % b), tmp = x ;
        x = y; y = tmp - (a / b) * y;
        return ans ;
    }
    
    int main() {
        int mx = 0 ; n = read() ;
        for(int i = 1; i <= n; i ++) {
            c[i] = read() , p[i] = read() , l[i] = read() ;
            mx = std::max(mx , c[i]) ;
        } mod = mx - 1 ;
        while(1) {
            mod ++ ;
            int flag = 0;
            for(int i = 1 ; i <= n ; i ++) {
                for(int j = i + 1 ; j <= n ; j ++) {
                    x = 0 , y = 0 ;
                    int k = ((p[i] - p[j]) % mod + mod) % mod , tmp = c[j] - c[i] ;
                    int gcd = exgcd(k , mod);
                    if(tmp % gcd) continue ;
                    int t = mod ;
                    x *= tmp / gcd ; t /= gcd ; t = std::abs(t) ;
                    x = ((x % t) + t) % t; 
                    if(x <= std::min(l[i] , l[j])) {flag = 1 ; break ;}
                }
                if(flag) break ;
            }
            if(!flag) { outn(mod) ; return 0 ; }
        }
    }
  • 相关阅读:
    SV——override
    SV——声明和例化
    SV——automatic
    SV——类型转换$cast
    C++——局部变量、全局变量、静态变量与动态对象的性质(转载)
    C++——动态分配内存
    异步复位,同步释放(转)
    异步复位中的recovery time和removal time(转)
    UVM——virtual sequencer和virtual sequence
    软件工程 实践者的研究方法 第38章答案
  • 原文地址:https://www.cnblogs.com/henry-1202/p/10067603.html
Copyright © 2020-2023  润新知