BZOJ传送门 Codevs传送门
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 1135 Solved: 518
[Submit][Status][Discuss]
Description
Input
第1行为一个整数N(1<=N<=15),即野人的数目。第2行到第N+1每行为三个整数Ci, Pi, Li (1<=Ci,Pi<=100, 0<=Li<=106 ),表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。
Output
仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于106。
Sample Input
3
1 3 4
2 7 3
3 2 1
Sample Output
6
该样例对应于题目描述中的例子。
HINT
Source
无情的丢链接被丢的可怜的链接
#include<cstdio>
#include<iostream>
using namespace std;
#define N 18
int c[N],p[N],l[N];
int n,m,x,y;
int exgcd(int a,int b,int &x,int &y){
if(!b){x=1,y=0;return a;}
int d=exgcd(b,a%b,x,y);
int t=x;x=y,y=t-a/b*y;
return d;
}
inline int abs(int x){return x<0?-x:x;}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&c[i],&p[i],&l[i]);
m=max(c[i],m);
}
for(int k=m;;k++){
bool flag=true;
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
int P=p[i]-p[j],C=c[j]-c[i];
int d=exgcd(P,k,x,y);
if(C%d) continue;
int now=x*C/d%(k/d);
if(now<0) now+=abs(k/d);
if(now<=min(l[i],l[j])){flag=false;break;}
}
if(!flag) break;
}
if(flag){printf("%d",k);break;}
}
return 0;
}