(复赛模拟试题)奶牛卧室(数论-同余)

Description
  奶牛们有一个习惯,那就是根据自己的编号选择床号。如果一头奶牛编号是a,并且有0..k-1一共k张床,那么她就会选择a mod k号床作为她睡觉的地点。显然,2头牛不能睡在一张床上。那么给出一些奶牛的编号,请你为她们准备一间卧室,使得里面的床的个数最少。

Input
  第一行是奶牛的个数n(1<=n<=5000);  第2到第n+1行是每头奶牛的编号Si(1<=Si<=1000000)。

Output

仅一行,是最少的床的数目。


分析:

        题目的意思,是求一个最小的k,使得给定的n个数对它取模的结果都不相同。

        同余的一般形式:a≡b(mod k) ,也就是a-b mod k =0,k是a-b的因数。要使a,b不同余,k就不能是a-b的因数。     

        设一个vis数组,可以先O(n)时间内把所有的a[i]-a[j]标记上,然后k从1开始枚举,若w*k已标记,那么标记vis[w]=1,vis[k]=1,再枚举下一个k。直到找到第一个w*k都没被标记的k,输出。


#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int INF=1000005;
const int maxn=5005;
int n,vis[INF],a[maxn];

int main()
{
//	freopen("in.txt","r",stdin);
	scanf("%d",&n);
	int maxs=0;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++) maxs=max(maxs,abs(a[i]-a[j])),vis[abs(a[i]-a[j])]=1;
	int flag,w,i;
	for(i=1;i<=maxs;i++)
	{
		flag=w=1;
		for(;i*w<=maxs;w++)
		{
			if(vis[i*w])
			{
				vis[i]=1,vis[w]=1;
				flag=0;
				break;
			}
		}
		if(flag) break;
	}
	printf("%d",i);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wwwengine/article/details/80989004
今日推荐