首页 > 其他 > 详细

bzoj1407【NOI2002】Savage

时间:2016-02-10 15:24:27      阅读:149      评论:0      收藏:0      [点我收藏+]

1407: [Noi2002]Savage

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1117  Solved: 510
[Submit][Status][Discuss]

Description

技术分享

Input

第1行为一个整数N(1<=N<=15),即野人的数目。第2行到第N+1每行为三个整数Ci, Pi, Li (1<=Ci,Pi<=100, 0<=Li<=106 ),表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。

Output

仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于106。

Sample Input

3
1 3 4
2 7 3
3 2 1

Sample Output

6

该样例对应于题目描述中的例子。

HINT

Source




分析两个野人的情况,设山洞数目为m,如果i和j在第x年相遇,那么可以得到一个同余方程ci+x*pi=cj+x*pj(mod m),即(pi-pj)*x=cj-ci(mod m)。所以要使两个野人不能相遇,只需该同余方程无解或者x比其中一个野人的寿命长。推广到n个野人两两不相遇,只需任意两个野人满足上述条件,因为n很小,所以可以枚举

我们一开始将m赋值为max{c[i]},每次判断m是否可行,如果可行即为答案,否则就将m加1。在判断m是否可行时要用到扩展欧几里得算法求。

注意:扩展欧几里得算法求满足ax=gcd(a,b) (mod b)的x的最小正整数解时,要将x对b/gcd(a,b)取模,而不是对b取模。





#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 20
using namespace std;
int n,mx,c[maxn],p[maxn],l[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void exgcd(int a,int b,int &d,int &x,int &y)
{
	if (!b)
	{
		d=a;x=1;y=0;
	}
	else
	{
		exgcd(b,a%b,d,y,x);
		y-=x*(a/b);
	}
}
inline bool judge(int m)
{
	F(i,1,n-1) F(j,i+1,n)
	{
		int d,x,y,dd=((c[j]-c[i])%m+m)%m,a=((p[i]-p[j])%m+m)%m;
		exgcd(a,m,d,x,y);
		if ((dd%d)!=0) continue;
		int mm=m/d;
		int k=(dd/d*x%mm+mm)%mm;
		if (k<=l[i]&&k<=l[j]) return false;
	}
	return true;
}
int main()
{
	n=read();
	mx=0;
	F(i,1,n)
	{
		c[i]=read();p[i]=read();l[i]=read();
		mx=max(mx,c[i]);
		c[i]--;
	}
	while (1)
	{
		if (judge(mx)) break;
		mx++;
	}
	printf("%d\n",mx);
}


bzoj1407【NOI2002】Savage

原文:http://blog.csdn.net/aarongzk/article/details/50649807

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!