• 暑假集训8.6数论专题—Savage(扩展欧几里得算法)


    题目描述:

    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。
     
    题解
     因为围成一个环因此能想到mod,接着我们可以你逆向思考,当ci+pi*x≡cj+pj*x(mod ans)存在时,ans不合法,由于数据较小,且不满足二分性质,我们可以由小到大枚举ans的大小,将式子化成(pi-pj)*x+ans*y=cj-ci,根据这个式子可以用扩展欧几里得解除x,根据x与li,lj的关系判断x是否合法。
     
    关于扩展欧几里得:
    上板子!
    LL exgcd(LL a,LL b,LL &x,LL &y){
        if(b==0){x=1;y=0;return a;}
        LL t=exgcd(b,a%b,x,y);LL x1=x;
        x=y;y=x1-a/b*y;
        return t;
    }
    View Code

    整题完整代码如下:

    #include<bits/stdc++.h>
    #define il inline
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=17;
    int n,p[N],c[N],l[N],m;
    il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;}
    LL exgcd(LL a,LL b,LL &x,LL &y){
        if(b==0){x=1;y=0;return a;}
        LL t=exgcd(b,a%b,x,y);
        LL x1=x;x=y;y=x1-a/b*y;return t;
    }
    il bool check(LL m){
        LL x,y,g;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++){
                g=exgcd((LL)(p[i]-p[j]),m,x,y);
                if(((c[j]-c[i])%g+g)%g)continue;
                x=x*(LL)(c[j]-c[i])/g;g=abs(g);
                x=(x%(m/g)+(m/g))%(m/g);
                if(x<=l[i]&&x<=l[j])return 0;
            }
        return 1;
    }
    int main()
    {
        n=read();for(int i=1;i<=n;i++)c[i]=read(),p[i]=read(),l[i]=read(),m=max(m,c[i]);
        while(!check((LL)m))m++;printf("%d
    ",m);
      return 0;
    }
    View Code
  • 相关阅读:
    iOS集成ijkplayer视频直播框架,遇到的bug和坑...
    push notification获取device token
    ios xcode Code signing failed 解决方案
    ios 返回指定导航控制器
    ios git 终端提交
    mysql问题集合
    mysql 备份和恢复
    cacti 异常问题
    硬盘各项检测
    LVS DR模式(直接路由模式)
  • 原文地址:https://www.cnblogs.com/Jessie-/p/9434449.html
Copyright © 2020-2023  润新知