bzoj 1407: [Noi2002]Savage【扩展欧几里得+中国剩余定理】

首先答案不会很大,所以枚举答案m,于是把问题转为了判定;
关于如何判定:
首先题目中虽然没说但是数据是按照初始洞穴编号排的序,所以并不用自己重新再排
假设当前答案为m,相遇时间为x,野人i和j,那么可以列出同余式;

\[x(p[i]-p[j])\equiv c[j]-c[i](mod\ m) \]

\[x(p[i]-p[j])+ym=c[j]-c[i] \]

于是可解exgcd。由于并不是互质的,所以最后的算天数需要m/d

#include<cstdio>
using namespace std;
const int N=20;
int n,mx,a[N],b[N],c[N],d,x,y;
void exgcd(int a,int b,int &d,int &x,int &y)
{
	if(!b)
	{
		d=a,x=1,y=0;
		return;
	}
	exgcd(b,a%b,d,y,x);
	y-=a/b*x;//!!
}
bool ok(int m)
{
	for(int i=1;i<n;i++)
		for(int j=i+1;j<=n;j++)
		{
			int aa=((a[j]-a[i])%m+m)%m,bb=((b[i]-b[j])%m+m)%m;
			exgcd(bb,m,d,x,y);
			if(aa%d)
				continue;
			aa/=d;
			int mm=m/d,k=(aa*x%mm+mm)%mm;
			if(k<=c[i]&&k<=c[j])
				return 0;
		}
	return 1;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&a[i],&b[i],&c[i]);
		mx=max(a[i],mx);
		a[i]--;
	}
	for(int i=mx;;i++)
		if(ok(i))
		{
			printf("%d\n",i);
			break;
		}
	return 0;
}
posted @ 2018-01-28 10:39  lokiii  阅读(127)  评论(0编辑  收藏  举报