• 【洛谷题解/NOI2002】P2421/NOI2002荒岛野人


    原题链接:https://www.luogu.com.cn/problem/P2421
    难度:提高+/省选-
    涉及知识点:扩展欧几里得算法(exgcd)

    题意

    n n n 只野人,第 i i i 只野人初始所在洞穴为 c [ i ] c[i] c[i],每年走过的洞穴数量为 p [ i ] p[i] p[i],寿命值为 l [ i ] l[i] l[i] 年。求在每个洞穴始终不会有两只及以上的野人同时出现在某一年的情况下,至少需要的洞穴数 M M M

    分析与解决

    在有 m m m 个洞穴时,对于第 i i i 只野人,第 x x x 年所在的洞穴编号应为 ( c [ i ] + x × p [ i ] )   m o d   m (c[i]+x\times p[i])\bmod m (c[i]+x×p[i])modm,且需要保证对于不同的两只野人,该式的值不会相同。那么对于这 n n n 只野人,两两建立如下方程,考虑是否有解。如果在有 m m m 个洞穴时两两建立的 n 2 n^2 n2 个方程都有解,则 m m m 个洞穴不够,还需要增加;如果都无解,则说明 m m m 个洞穴可行。
    c [ i ] + x × p [ i ] ≡ c [ j ] + x × p [ j ] (   m o d     m ) c[i]+x\times p[i]\equiv c[j]+x\times p[j](\bmod \ m) c[i]+x×p[i]c[j]+x×p[j](mod m)然后再做如下推导:
    由同余式变换规则得,
    x × p [ i ] − x × p [ j ] ≡ c [ j ] − c [ i ] (   m o d     m ) x\times p[i]-x\times p[j]\equiv c[j]-c[i](\bmod \ m) x×p[i]x×p[j]c[j]c[i](mod m)
    由分配律得,
    x × ( p [ i ] − p [ j ] ) ≡ c [ j ] − c [ i ] (   m o d     m ) x\times (p[i]-p[j])\equiv c[j]-c[i](\bmod \ m) x×(p[i]p[j])c[j]c[i](mod m)
    整理得,
    x × ( p [ i ] − p [ j ] ) − m y = c [ j ] − c [ i ] x\times (p[i]-p[j])-my=c[j]-c[i] x×(p[i]p[j])my=c[j]c[i]
    所以可以直接套用扩展欧几里得算法,如果在有 m m m 个洞穴时,求 x x x 的最小解,如果 x ≤ min ⁡ ( l [ i ] , l [ j ] ) x\leq \min(l[i],l[j]) xmin(l[i],l[j]),说明在有 m m m 个洞穴,当前的 x x x 是一个解,因为所有野人都活着,那就是有解的情况,而我们要求的是无解的情况,因而排除。

    输入数据时记录一下最大的初始洞穴编号,即在不考虑冲突的情况最少需要的洞穴数。然后从该值开始增加,每次 check 一下 i i i 个洞穴是否可行即可。

    AC代码

    #include 
    #include 
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 20;
    int n, m, ans;
    ll x, y;
    int C[N], P[N], L[N];
    
    ll exgcd (ll a, ll b, ll &x, ll &y)
    {
        if (!b)
        {
            x = 1, y = 0;
            return a;
        }
        int d = exgcd (b, a % b, y, x);
        y -= a / b * x;
        return d;
    }
    
    bool check (int m)
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = i + 1; j <= n; j++)
            {
                ll a = P[i] - P[j], b = m, c = C[j] - C[i];
                int d = exgcd (a, b, x, y);
                if (c % d) continue;
                a /= d, b /= d, c /= d;
                if (b < 0) b = -b; //纠正负数
                x = (x * c %  b + b) % b;
                if (x <= L[i] && x <= L[j]) return false; //年份x在他们的寿命范围内,有解,不行
            }
        }
        return true;
    }
    
    int main()
    {
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            cin >> C[i] >> P[i] >> L[i];
            m = max(m, C[i]);
        }
    
        for (int i = m;; i++)
        {
            if (check(i))
            {
                cout << i << endl;
                return 0;
            }
        }
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
  • 相关阅读:
    Java正则表达式 提取文本中所有的匹配数据
    网络运维的重要性
    基于Python实现的心脏衰竭致死相关因素研究
    2023第十四届蓝桥杯国赛 C/C++ 大学 B 组 (赛后记录)
    Python中处理HTTP异常和错误的策略
    Maven之POM介绍
    【仿牛客网笔记】 Kafka,构建TB级异步消息系统——优化登陆模块、Kafka入门、Spring整合Kafka
    docker试验步骤与截图(无用)
    前端CSS设置字体
    【PTA】蛇形矩阵
  • 原文地址:https://blog.csdn.net/lightningcs/article/details/126586019