• [NOI2002] Savage 解题报告(扩展欧几里得)


    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1407

    Description

    克里特岛以野人群居而著称。岛上有排列成环行的M个山洞。这些山洞顺时针编号为1,2,…,M。岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi个洞住下来。每个野人i有一个寿命值Li,即生存的年数。下面四幅图描述了一个有6个山洞,住有三个野人的岛上前四年的情况。三个野人初始的洞穴依次为1,2,3;每年要走过的洞穴数依次为3,7,2 寿命值依次为4,3,1。 

     

    奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?
     

    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

    比赛的时候写这题我写了个瞎二分,然后最后半个小时发现不满足二分性质,就又随性的加上了枚举,于是...得到了20分的安慰分

    好吧其实正解就是枚举,我们从小到大枚举山洞的个数

    怎么判断是否会有野人相遇呢?若有m个山洞,对于野人i,j,他们相遇的充要条件就是:

    Ci+xPi≡Cj+xPj (mod m)

    移项可得:Ci-Cj≡x(Pj-Pi) (mod m)

    于是我们设 x(Pj-Pi)+ym=Ci-Cj

    设A=Pj-Pi B=m C=Ci-Cj,考虑解不定方程Ax+By=C

    对于x的最小正整数解,若满足x<=min(L[i],L[j]),那么两个野人就可以在有生之年相遇

    既然这样,我们依次枚举两个野人就好

    怎么解不定方程...就不说了

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int maxn=25;
    int n,minc;
    int c[maxn],p[maxn],l[maxn];
    int gcd(int x,int y) {if (x%y==0) return y;else return gcd(y,x%y);}
    void exgcd(int A,int B,int &x,int &y)
    {
        if (!B)
        {
            x=1;y=0;return;
        }
        exgcd(B,A%B,x,y);
        int z=x;x=y;y=z-y*(A/B);
    }
    bool check(int t)
    {
        for (int i=1;i<=n;i++)
        {
            for (int j=i+1;j<=n;j++)
            {
                int A=p[i]-p[j],B=t,C=c[j]-c[i],x,y;    
                int gg=gcd(A,B);
                if (C%gg==0)
                {
                    A/=gg;B/=gg;C/=gg;
                    exgcd(A,B,x,y);
                    B=abs(B);
                    x=((x*C)%B+B)%B;
                    while (!x) x+=B;
                    if (x<=min(l[i],l[j])) return 0;
                }
            }
        }
        return 1;
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
        scanf("%d%d%d",c+i,p+i,l+i);
        minc=max(minc,c[i]);
        }
        for (int t=minc;;t++) if (check(t)) {printf("%d",t);break;}
        return 0;
    }
  • 相关阅读:
    使用Python验证常见的50个正则表达式
    空气开关为何叫空气开关?它跟空气有何关系?
    YOLO 算法最全综述:从 YOLOv1 到 YOLOv5
    深入理解部分 SQL 语句执行慢的原因
    KNN(k-nearest-neighbor)算法
    聚类分析方法
    SQL Database学习笔记
    statistic学习笔记
    MapReduce中的排序
    weka打开提示内存不足的解决方法
  • 原文地址:https://www.cnblogs.com/xxzh/p/9287006.html
Copyright © 2020-2023  润新知