Beyond the Void
BYVoid
NOI 2002 荒岛野人

这是一个数论问题。首先说给定一个M,判断M是否可行。假设两个野人为i和j,设两个人在第x年相遇,则C[i] + x * P[i] === C[j] + x * P[j] ( Mod M ),x的最小非负解应至少大于L[i]和L[j]的任意一个(相遇时已至少有一个人死亡),或者无解(两人不可能相遇)。对于每对(i,j)都进行检查, 如果所有人都不能相遇,则说明M是一个可行解。对于M应从小到大枚举,这样首次满足条件的M就是解了。

上述式子转化为标准线性同余方程就是 (P[i]-P[j]) * x === C[j] - C[j] ( Mod M ),应保证P[i]-P[j]不为负数。要注意M最小值应不小于任意一个C[i]。

/* 
 * Problem: NOI2002 savage
 * Author: Guo Jiabao
 * Time: 2009.5.20 22:36
 * State: Solved
 * Memo: 线性同余方程
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
const int MAXN=16;
using namespace std;
int C[MAXN],P[MAXN],L[MAXN],N,M,S;

void init()
{
	freopen("savage.in","r",stdin);
	freopen("savage.out","w",stdout);
	scanf("%d",&N);
	S=N;
	for (int i=1;i<=N;i++)
	{
		scanf("%d%d%d",&C[i],&P[i],&L[i]);
		if (C[i] > S)
			S=C[i];
	}
}
int extend_gcd(int a,int b,int &x,int &y)
{
	if (!b)
	{
		x=1;y=0;
		return a;
	}
	else
	{
		int t,d;
		d=extend_gcd(b,a%b,x,y);
		t=x; x=y; y=t-(a/b)*y;
		return d;
	}
}
int mod_eq(int a,int b,int n)
{
	int d,x,y;
	d = extend_gcd(a,n,x,y);
	if (b%d) return -1;
	x = x * b / d % (n / d);
	x = ( x + n / d ) % ( n / d );
	return x;
}
bool legal()
{
	int i,j,x,a,b;
	for (i=1;i<N;i++)
	{
		for (j=i+1;j<=N;j++)
		{
			a=P[j]-P[i];b=C[i]-C[j];
			if (a<0 && b<0)
				a=-a,b=-b;
			if (a<0 && b>0)
				x=a,a=b,b=x;
			x=mod_eq(a,b,M);
			if (!(x==-1 || x>L[i] || x>L[j]))
				return false;
		}
	}
	return true;
}
void solve()
{
	for (M=S;!legal();M++);
	printf("%dn",M);
}
int main()
{
	init();
	solve();
	return 0;
}
<h2><span class="mw-headline">荒岛野人 </span></h2>

【问题描述】

克里特岛以野人群居而著称。岛上有排列成环行的M个山洞。这些山洞顺时针编号为1,2,…,M。岛上住着N个野人,一开始依次住在山洞 C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi个洞住下来。每个野人i有一个寿命值Li,即生存的年数。下面四幅图描述了一个有6个 山洞,住有三个野人的岛上前四年的情况。三个野人初始的洞穴编号依次为1,2,3;每年要走过的洞穴数依次为3,7,2;寿命值依次为4,3,1。

<a class="image" title="Image:Savage1.gif" href="http://www.ruvtex.cn/wiki/Image:Savage1.gif"><img src="http://www.ruvtex.cn/mw/images/8/87/Savage1.gif" alt="Image:Savage1.gif" width="246" height="138" /></a>

<a class="image" title="Image:Savage2.gif" href="http://www.ruvtex.cn/wiki/Image:Savage2.gif"><img src="http://www.ruvtex.cn/mw/images/e/e8/Savage2.gif" alt="Image:Savage2.gif" width="238" height="103" /></a>

<a class="image" title="Image:Savage3.gif" href="http://www.ruvtex.cn/wiki/Image:Savage3.gif"><img src="http://www.ruvtex.cn/mw/images/4/45/Savage3.gif" alt="Image:Savage3.gif" width="230" height="131" /></a>

<a class="image" title="Image:Savage4.gif" href="http://www.ruvtex.cn/wiki/Image:Savage4.gif"><img src="http://www.ruvtex.cn/mw/images/2/21/Savage4.gif" alt="Image:Savage4.gif" width="238" height="110" /></a>

奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?
【输入文件】

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

输出文件仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于106。
【样例输入】
<pre>3
1 3 4
2 7 3
3 2 1</pre>
【样例输出】
<pre>6</pre>
【样例说明】

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

上次修改时间 2017-05-22

相关日志