[ NOI 2002 ] 荒島野人
阿新 • • 發佈:2018-11-06
\(\\\)
Description
- \(n\le 15\),保證答案小於 \(10^6\)。
\(\\\)
Solution
首先要注意到答案不具有單調性,手搓兩組樣例就能發現剩餘系不同重合位置是不同的。
然後想到從小往大列舉答案然後驗證。注意下界是 \(max\{C_i\}\)
驗證選擇最暴力的方法即可。
加入現在列舉共有 \(len\) 個洞。
考慮兩個野人 \(i,j\) ,假如說 \(k\) 年後他們重合,那麼 \(k\) 應該滿足
\[ C_i+kP_i\equiv C_j+kP_j\pmod{len} \]
移項
\[ k(P_i-P_j)\equiv C_j-C_i\pmod{len} \]
這不是同餘方程麼.....直接擴歐求一個最小的正整數解 \(k\) 即可。
如果 \(k>min(L_i,L_j)\) 證明在相遇之前他們之中就有人死了,所以沒有問題。
特殊的,如果無解代表他們這輩子也碰不到,也是合法的。
複雜度 \(O(ans\times 15^2\times log 10^6)\)
\(\\\)
Code
#include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 20 #define R register #define gc getchar using namespace std; inline int rd(){ int x=0; bool f=0; char c=gc(); while(!isdigit(c)){if(c=='-')f=1;c=gc();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();} return f?-x:x; } int n,mx,c[N],p[N],l[N]; void exgcd(int a,int b,int &x,int &y,int &g){ if(!b){g=a;x=1;y=0;} else{exgcd(b,a%b,y,x,g);y-=a/b*x;} } inline bool valid(int now){ R int a,b,d,x,y,g; for(R int i=1;i<n;++i) for(R int j=i+1;j<=n;++j){ b=now; a=(p[i]-p[j]+b)%b; d=(c[j]-c[i]+b)%b; exgcd(a,b,x,y,g); if(d%g!=0) continue; a/=g; b/=g; d/=g; x=(x*d%b+b)%b; if(x<=min(l[i],l[j])) return 0; } return 1; } int main(){ n=rd(); if(n==1){puts("1");return 0;} for(R int i=1;i<=n;++i){ mx=max(mx,c[i]=rd()); p[i]=rd(); l[i]=rd(); } while(!valid(mx)) ++mx; printf("%d\n",mx); return 0; }