BZOJ 1407
1407: [Noi2002]Savage
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 2350 Solved: 1054
[Submit][Status][Discuss]
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
1 3 4
2 7 3
3 2 1
Sample Output
6
//该样例对应于题目描述中的例子。
//该样例对应于题目描述中的例子。
Source
HINT
很容易发现是解一个同余方程k(p[j]-p[i])=c[i]-c[j] mod x(枚举x)只要解小于l[i]和l[j]就不满足条件
数据小,随便枚举
扩展欧几里得!!
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define N 20 using namespace std; int n,c[N],p[N],l[N],k; void exgcd(int a,int b,int &d,int &x,int &y) { if(b==0) { d=a;x=1;y=0; } else { exgcd(b,a%b,d,y,x); y-=x*(a/b); } } int ok(int mod) { for(int i=1;i<=n-1;i++) for(int j=i+1;j<=n;j++) { int a=((p[i]-p[j])%mod+mod)%mod,b=((c[j]-c[i])%mod+mod)%mod,x,y,d; exgcd(a,mod,d,x,y); //printf("%d %d %d %d %d\n",a,mod,d,x,y); if(b%d!=0)continue; b/=d; int mm=mod/d; int ans=((b*x)%mm+mm)%mm; if(ans<=min(l[i],l[j]))return 0; } return 1; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d%d",&c[i],&p[i],&l[i]); k=max(k,c[i]); c[i]--; } for(;;k++) if(ok(k)) { printf("%d",k); return 0; } return 0; }