BZOJ1407 [Noi2002]Savage

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
//该样例对应于题目描述中的例子。

HINT

Source

 
 
正解:搜索+扩展欧几里得
解题报告:
  今天上午考试的T2,一上来一看,这不是板子题吗?然后就没有然后了...
  考虑枚举一共有多少个山洞,每次对于当前的山洞个数,两两check一下,看一下是否会冲突。check的方式很简单,就是直接解他们相遇的不定方程,很容易根据他们的信息得到一个方程,看一下最小正整数解是否在他们的寿命范围内。可以发现这样做的理论复杂度是TLE的,但是很显然我们每次check复杂度远远不到n^2,所以不会T。
 
 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 using namespace std;
14 typedef long long LL;
15 const int inf = (1<<30);
16 const int MAXN = 15+30;
17 int n,minl,a,b,c;
18 int ini[MAXN],p[MAXN],L[MAXN];
19 //c[i]+p[i]*x=c[j]+p[j]*x-now*y   ==>  (c[i]-c[j])*x+now*y=c[j]-c[i]
20 
21 inline int getint()
22 {
23     int w=0,q=0; char c=getchar();
24     while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
25     while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
26 }
27 
28 inline int gcd(int x,int y){ 
29     if(y==0) return x;
30     return gcd(y,x%y);
31 }
32 
33 inline void extend_gcd(int a,int b,int &x,int &y){
34     if(b==0) { 
35     x=1;
36     y=0; 
37     return ; 
38     }
39     extend_gcd(b,a%b,x,y);
40     int lin=x; x=y; 
41     y=lin-(a/b)*y;
42 }
43  
44 inline void check(int now){//两两检查合法性
45     int gong,x,y;
46     for(int i=1;i<n;i++) 
47     for(int j=i+1;j<=n;j++) {
48         a=(p[i]-p[j]); b=now; c=(ini[j]-ini[i]);  gong=gcd(a,b);
49         if(c%gong!=0) continue; //无解
50         a=a/gong; b=b/gong; c=c/gong;
51         extend_gcd(a,b,x,y); 
52         if(b<0) b=-b;
53         x=x*c; x%=b; x+=b; x+=b; x%=b;
54         if(x<=L[i] && x<=L[j]) return ;
55     }
56     printf("%d",now);
57     exit(0);
58 }
59 
60 inline void work(){
61     n=getint();  for(int i=1;i<=n;i++) ini[i]=getint(),p[i]=getint(),L[i]=getint();
62     for(int i=1;i<=n;i++) minl=max(minl,ini[i]);//至少是ini[i]的最大值
63     for(;;minl++) check(minl);
64 }
65  
66 int main()
67 {
68     work();
69     return 0;
70 }

 

 
 
posted @ 2016-09-27 14:48  ljh_2000  阅读(277)  评论(0编辑  收藏  举报