jzoj1158-荒岛野人【扩欧,gcd,同余方程】

正题


大意

有n个野人,每个野人有一个初始山洞 Ci C i ,每次向前移动距离 Pi P i ,寿命 Li L i ,如果野人走到了最后一个山洞那么继续就好回到第一个山洞,求至少多少个山洞才可以让野人们不会发生冲突。
这里写图片描述


解题思路

我们可以枚举答案,然后我们要判断是否冲突,我们可以枚举两个野人然后列出式子:

Ci+PixCj+Pjx(mod  l) C i + P i x ≡ C j + P j x ( m o d     l )

如果这个式子有解且最小解
x<=Li/Lj x <= L i / L j 那么就会有冲突。
我们先把式子转换一下
(CiCj)+(PiPj)x0(mod  l) ( C i − C j ) + ( P i − P j ) x ≡ 0 ( m o d     l )

(CiCj)+(PiPj)x=ly ( C i − C j ) + ( P i − P j ) x = l y

(PiPj)xly=(CiCj) ( P i − P j ) x − l y = ( C i − C j )

然后我们进行扩欧


代码

#include<cstdio>
#include<algorithm>
using namespace std;
int x,y,n,c[16],p[16],l[16],maxc,d,A,B,g;
bool flag;
int gcd(int a,int b)//同余
{
    if (b==0)
    {
        x=1;
        y=0;
        return a;
    }
    d=gcd(b,a%b);
    int k=x;
    x=y;
    y=k-a/b*y;
    return d;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&c[i],&p[i],&l[i]);
        maxc=max(maxc,c[i]);
    }
    while (1)
    {
        flag=false;
        for (int i=1;i<n;i++)
        {
          for (int j=i+1;j<=n;j++)
          {
            A=c[i]-c[j];B=p[j]-p[i];
            if (B<0)
            {
              A=-A;
              B=-B;//取反,因为是   -ly
            }
            d=gcd(B,maxc);
            g=maxc/d;
            g=((x*(A/d))%g+g)%g;//最小解
            if (!(A%d)&&g<=l[i]&&g<=l[j])//判断
              {flag=true;break;}
          }
          if (flag) break;
        }
        if (!flag) break;
        maxc++;//枚举
    }
    printf("%d",maxc);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值