• CodeVS1747_NOI2002_荒岛野人_Savage_C++


      题目:http://codevs.cn/problem/1747/

      对于一个环,我们经常用取余来表示它走过若干圈后的位置

      那么第 i 个野人第 x 年时所在的位置可表示为:(c[i]+p[i]*x)%m (若结果为 0 则变为 m)

      若两个野人不产生冲突,则在它们俩最小的寿命之内,每一年的位置都会不同

      可列出不等式,对于第 i 和第 j 号野人,(c[i]+p[i]*x)%m!=(c[j]+p[j]*x)%m

      但是不等式十分不好解,则把它转化为等式,并做变换

      (c[i]+p[i]*x)%m=(c[j]+p[j]*x)%m

      c[i]+p[i]*x+my1=c[j]+p[j]*x+my2

      p[i]*x-p[j]*x+my1-my2=c[j]-c[i]

      (p[i]-p[j])*x+m(y1-y2)=c[j]-c[i]

      其中 y1 与 y2 取多少我们不关心,因为它只是一个走多少圈的问题,把它合为 y

      再设 a=p[i]-p[j] , b=m , c=c[j]-c[i]

      方程化为 ax+by=c

      这就是一个解不等式的问题,用 exgcd 求

      (exgcd 扩展欧几里德算法详解:

        http://www.cnblogs.com/hadilo/p/5914302.html

      要求无解(不会遇上)或者得到的最小解大于 min(l[i],l[j]) (在寿命短的那个野人死后才遇上)

      那么枚举 m ,然后 n2 的判断是否有会遇上的情况即可

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 using namespace std;
     8 
     9 const int N=16;
    10 int d[N],p[N],l[N],x,y,n,m;
    11 inline int gcd(int a,int b)
    12 {
    13     return b?gcd(b,a%b):a;
    14 }
    15 inline void exgcd(int a,int b)
    16 {
    17     if (b)
    18         {
    19             exgcd(b,a%b);
    20             int k=x;
    21             x=y;
    22             y=k-a/b*y;
    23         }
    24     else y=(x=1)-1;
    25 }
    26 bool check()
    27 {
    28     int i,j,a,b,c,r;
    29     for (i=1;i<n;i++)
    30         for (j=i+1;j<=n;j++)
    31             {
    32                 a=p[i]-p[j];
    33                 b=m;
    34                 c=d[j]-d[i];
    35                 r=gcd(a,b);
    36                 if (c%r) continue;
    37                 exgcd(a,b);
    38                 b=abs(b/r);
    39                 x=(x/r*c%b+b)%b;
    40                 if (!x) x+=b;
    41                 if (x<=min(l[i],l[j])) return 1;
    42             }
    43     return 0;
    44 }
    45 int main()
    46 {
    47     int i,s=0;
    48     scanf("%d",&n);
    49     for (i=1;i<=n;i++)
    50         {
    51             scanf("%d%d%d",&d[i],&p[i],&l[i]);
    52             s=max(d[i],s);
    53         }
    54     for (m=s;check();m++);
    55     printf("%d
    ",m);
    56     return 0;
    57 }

    版权所有,转载请联系作者,违者必究

    联系方式:http://www.cnblogs.com/hadilo/p/5932395.html

  • 相关阅读:
    HDU 3339 In Action 最短路+01背包
    hash与map的区别联系应用(转)
    POJ
    欧几里德与扩展欧几里德算法(转)
    POJ
    第三届蓝桥杯C++B组省赛
    第四届蓝桥杯C++B组省赛
    第五届蓝桥杯C++B组省赛
    第六届蓝桥杯C++B组省赛
    线段树为什么要开4倍空间
  • 原文地址:https://www.cnblogs.com/hadilo/p/5951091.html
Copyright © 2020-2023  润新知