Description
Input
第1行为一个整数N(1<=N<=15),即野人的数目。
第2行到第N+1每行为三个整数Ci, Pi, Li表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。
(1<=Ci,Pi<=100, 0<=Li<=10^6 )
Output
仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于10^6。
Sample Input
3
1 3 4
2 7 3
3 2 1
Sample Output
6
题解
复习了一把Exgcd,顺带填了之前的坑嘿嘿嘿
对于两个野人i,j,可以列出一个同余方程
c[i]+p[i]*x=c[j]+p[j]*x (mod m)
然后拆一下就变成了(p[i]-p[j])*x-m*y=c[j]-c[i]
exgcd求出x的最小解,判一下是不是小于min(l[i],l[j]),然后这就是check了
那么我们枚举m,在check里面枚举i,j,exgcd判断,由于n<=15所以就一通乱gay就好
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
/*
c[i]+p[i]*x=c[j]+p[j]*x (mod m)
(p[i]-p[j])*x-m*y=c[j]-c[i]
*/
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(a==0)
{
x=0;y=1;
return b;
}
else
{
LL tx,ty;
LL d=exgcd(b%a,a,tx,ty);
x=ty-(b/a)*tx;
y=tx;
return d;
}
}
int n;
LL c[30],p[30],l[30];
bool check(int m)
{
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
LL a=p[i]-p[j],b=(LL)m,k=c[j]-c[i];
LL x,y;
LL d=exgcd(a,b,x,y);
if(k%d)continue;
x=x*(k/d);x=x%(b/d);
if(x<0)x+=abs(b/d);
if(x<=min(l[i],l[j]))return false;
}
return true;
}
int main()
{
scanf("%d",&n);
LL ans=n;
for(int i=1;i<=n;i++){scanf("%lld%lld%lld",&c[i],&p[i],&l[i]);ans=max(ans,c[i]);}
for(ans;ans<=1000000;ans++)if(check(ans)){printf("%lld\n",ans);return 0;}
return 0;
}