• P2421 [NOI2002]荒岛野人


    题目背景

    原 A-B数对(增强版)参见P1102

    题目描述

    克里特岛以野人群居而著称。岛上有排列成环行的M个山洞。这些山洞顺时针编号为1,2,…,M。岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi个洞住下来。

    每个野人i有一个寿命值Li,即生存的年数。

    下面四幅图描述了一个有6个山洞,住有三个野人的岛上前四年的情况。三个野人初始的洞穴编号依次为1,2,3;每年要走过的洞穴数依次为3,7,2;寿命值依次为4,3,1。

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

    输入格式

    第1行为一个整数N(1<=N<=15),即野人的数目。

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

    输出格式

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

    输入输出样例

    输入 #1

    3
    1 3 4
    2 7 3
    3 2 1

    输出 #1

    6
    

    解题思路

      首先,对于第i个野人和第j个野人,我们都希望Ci+k*Pi≡Cj+k*Pj(mod ans)的k>他们两个寿命最短的一个,因为就算遇到了,也死了.........

      然后就有k*(Pi-Pj)+m*ans=Cj-Ci,就是裸的exgcd了................

    题解

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int c[101],p[101],l[101];
     4 int x,y;
     5 int exgcd(int a,int b)
     6 {
     7     if(b==0)
     8     {
     9         x=1;
    10         y=0;
    11         return a;
    12     }
    13     int g=exgcd(b,a%b); 
    14     int z=x;
    15     x=y;
    16     y=z-(a/b)*y;
    17     return g;
    18 }
    19 int main()
    20 {
    21     int n,maxc=0;
    22     scanf("%d",&n);
    23     for(int i=1;i<=n;i++)
    24     {
    25         scanf("%d%d%d",&c[i],&p[i],&l[i]);
    26         maxc=max(maxc,c[i]);//肯定从最大的编号开始枚举 
    27     }
    28     for(int ans=maxc;;ans++)//枚举山洞的数量 
    29     {
    30         bool flag=0;
    31         for(int i=1;i<=n;i++)
    32         {
    33             for(int j=i+1;j<=n;j++)//双层循环,每两个野人一个同余方程 
    34             {
    35                 int k=p[i]-p[j];
    36                 k=(k%ans+ans)%ans;
    37                 int g=exgcd(k,ans);//最大公约数 
    38                 if((c[j]-c[i])%g)//如果这个解不合法 
    39                     continue;//说明永远也碰不着 
    40                 x*=((c[j]-c[i])/g);//求要追上的年数 
    41                 int mod=ans/g;
    42                 x=(x%mod+mod)%mod;
    43                 if(x<=min(l[i],l[j]))//如果追上了 
    44                 {
    45                     flag=1;//洞穴数量不合法标记退出 
    46                     break;
    47                 }
    48             }
    49             if(flag)break;
    50         }
    51         if(flag)continue;
    52         printf("%d",ans);//合法了就输出 
    53         return 0;
    54     }
    55 }
  • 相关阅读:
    SQL 耗时优化
    Visual Studio 使用 Web Deploy 发布远程站点
    Windows API 调用示例
    Windows Server 2016 配置 IIS 的详细步骤
    SQL Server 游标的使用示例
    IIS 常用命令
    Nginx的使用和配置
    Nginx安装和配置
    mysql中关于时间的总结
    时间格式转换
  • 原文地址:https://www.cnblogs.com/hualian/p/11252595.html
Copyright © 2020-2023  润新知