正题
大意
有n个野人,每个野人有一个初始山洞
Ci
C
i
,每次向前移动距离
Pi
P
i
,寿命
Li
L
i
,如果野人走到了最后一个山洞那么继续就好回到第一个山洞,求至少多少个山洞才可以让野人们不会发生冲突。
解题思路
我们可以枚举答案,然后我们要判断是否冲突,我们可以枚举两个野人然后列出式子:
Ci+Pix≡Cj+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 那么就会有冲突。
我们先把式子转换一下
(Ci−Cj)+(Pi−Pj)x≡0(mod l)
(
C
i
−
C
j
)
+
(
P
i
−
P
j
)
x
≡
0
(
m
o
d
l
)
(Ci−Cj)+(Pi−Pj)x=ly
(
C
i
−
C
j
)
+
(
P
i
−
P
j
)
x
=
l
y
(Pi−Pj)x−ly=(Ci−Cj)
(
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);
}