1. 程式人生 > >【NOI2002/LOJ10215】荒島野人

【NOI2002/LOJ10215】荒島野人

解析:

  擴充套件歐幾里得。   題目就是要求解:c[i]+kp[i]c[j]+kp[j](modM)c[i]+k*p[i]\equiv c[j]+k*p[j](modM)   轉化一下:a(p[i]p[j])bmc[j]c[i](modM)a*(p[i]-p[j])-b*m\equiv c[j]-c[i](modM)   於是用擴充套件歐幾里得解最小aa,若無解或aminl[i],l[j]a\geq min(l[i],l[j])

[i],l[j],則滿足題意

程式碼:

#include <bits/stdc++.h>
using namespace std;

const int Max=20;
int n,m,x,y,mx,ans;
int c[Max],p[Max],l[Max];

inline void init()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d%d%d",&c[i],&p[i],&l[i]),mx=max(mx,c[i]);
}
inline int GCD(int a,int b){return
!b?a:GCD(b,a%b);} inline void exgcd(int a,int b) { if(!b) x=1,y=0; else { exgcd(b,a%b); int t=x; x=y,y=t-a/b*x; } } inline bool check(int mid) { for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) { int gcd=GCD(p[i]-p[j],mid); if((c[j]-c[i])%gcd) continue; int a=(p[i]-p[
j])/gcd,b=mid/gcd; exgcd(a,b),b=abs(b); //注意abs x=(x*(c[j]-c[i])/gcd%b+b)%b; if(!x) x+=b; // 注意 if(x<=min(l[i],l[j])) return 0; } return 1; } inline void solve() { for(int i=mx;;i++) if(check(i)) {ans=i;break;} cout<<ans; } int main() { init(); solve(); return 0; }