• ☆[noi2002]荒岛野人


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

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


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


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


    样例输入 Sample Input
    3
    1 3 4
    2 7 3
    3 2 1

    样例输出 Sample Output
    6


    时间限制 Time Limitation
    1s


    注释 Hint
    1s


    来源 Source
    noi 2002 day2

        思路:

        这道题其实和那个青蛙约会很像的哇,这道题的野人也就15个不直接扩展欧几里得不会超时的,因为你要让每次没有两个野人在同一个山洞里(可能是野人不喜欢一起讨论哲学♂的事吧哈哈,我们假设这一全有m个山洞,我们用结构体存一下每个野人的寿命s[i].l,每个野人的初始山洞s[i].c,每个野人每次移动山洞的个数a[i].p,所以我们可以得出一个方程s[i].c+x*s[i].p≡s[j].c+x*s[j].p(mod m)。这个方程可以化简为(s[i].p-s[j].p)*x-my=s[j].c-s[i].c;我们要时这个方程无解(这样就表示野人i他永远也追不上野人j)因为每个野人还有寿命,所以当我们求出的x>min(s[i].l,s[j].l)时这时的山洞数也当然成立,因为野人i在死后才会追上野人j,所以他俩也当然不会住在一起哲♂学了哇。。。

        超时看下方↓

        {这样是不是就A了呢??当然不是你会发现超时了........这是为什么呢?(我当时也是稀里糊涂的超了)

        我还在纳闷怎么会超时,然后发现,当你在用扩展欧几里得的定理求a/d*x+b/d*y=c/d的时候要用到

        t=gcd(a,b);又因为a=s[i].p-s[j].p;这显然可以发现野人i每次跑的距离可以比野人j的少哇,所以肯定可能

        为负数...........然后你将b取个abs就好了}

        代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct shadow
    {
        int c,p,l;
    }s[1000];
    int x,y;
    int gcd(int a,int b)
    {return b==0?a:gcd(b,a%b);}
    void exgcd(int a,int b,int &x,int &y)
    {
        if(b==0)
        {
            x=1;
            y=0;
            return;
        }
        exgcd(b,a%b,x,y);
        int t=x;
        x=y;
        y=t-a/b*y;
    }
    int n;
    bool work(int m)
    {
        int a,b,c,t,x,y;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                a=s[i].p-s[j].p;
                c=s[j].c-s[i].c;
                b=m;
                t=gcd(a,b);
                if(c%t==0)
                {
                    a/=t;b/=t;c/=t;
                    exgcd(a,b,x,y);
                    b=abs(b);
                    x=((c*x)%b+b)%b;
                    if(!x)
                        x+=b;
                    if(x<=min(s[i].l,s[j].l))
                        return 0;
                }
            }
        }
        return 1;
    }
    int main()
    {
        cin>>n;
        int maxx=0;
        for(int i=1;i<=n;i++)
        {
            cin>>s[i].c>>s[i].p>>s[i].l;
            maxx=max(maxx,s[i].c);
        }
        for(int i=maxx;;i++)
            if(work(i))
            {
                cout<<i<<endl;
                return 0;
            }
        return 0;
    }
    ٩(๑>◡<๑)۶
  • 相关阅读:
    java面向对象(五)之多态
    java集合(list,set,map)
    jQuery基础
    Numpy详解
    Pandas详解一
    Linux 解压缩
    Linux 磁盘挂载
    Linux 磁盘管理
    su和sudo命令详解
    Linux查看文件命令
  • 原文地址:https://www.cnblogs.com/lcyhaha/p/7464828.html
Copyright © 2020-2023  润新知