Minimum Modular单纯数学

题目描述

N个不同的数a[1],a[2]...a[n],你可以从中去掉K个数,并且找到一个正整数M,使得剩下的N - K个数,Mod M的结果各不相同,求M的最小值。
Input
第1行:2个数N, K,中间用空格分隔,N表示元素的数量,K为可以移除的数的数量(1 <= N <= 5000, 0 <= K <= 4, 1 <= a[i] <= 1000000)。
Output
输出符合条件的最小的M。

题目分析:

首先可以给定出一个暴力的方法,那就是枚举所有的i,从1开始,然后统计余数相同的数一共多出来多少个,很明显,当多出来的数大于k时则不满足情况,从小到大枚举i遇到第一个满足要求的返回即可。

但是这样很显然会超时,时间复杂度为O(N*10^6),这里有一个优化如下:

统计出所有的两两组合差值的情况,如有两个数x,y如果x % i = y %m,那么(x - y) % i = 0,统计差值将在后面的计算中发挥作用。当算法枚举到一个m的时候,那么我们就可以在O(10^6/i)的时间内统计出所有差值满足(x-y)%i=0的组数,只要统计差值为1*i, 2*i, ... , p*i <= 10^6的总数tmp即可。那么这个组数与拥有相同余数多出来的数有什么关系呢?如果(x - y) % i = 0只能够说明他们对m的余数相等,但是不能保证tmp组的余数均相等或者均不相等。

那么如果所有的tmp组每组的余数不同:如tmp = 5, i = 13.  存在如下五组:(13, 26), (14, 27), (15, 28), (16, 29), (17, 30)。那么重复的数就是5。
如果所有tmp组每组的余数都相同:如tmp = 6, i= 13. 存在如下五组:(13, 26), (13, 39), (13, 52), (26, 39), (26, 52), (39, 52)。那么重复的数就是3。

而可能的取值就是在这两个数之间的,我们取一个下限,即如果下限超过了k则可以判定退出了。k+1个相同余数的数就将不满足题意,他们一共能够生成:C(2, k+1)种组合情况,所以每次验证之前加上这个验证即可。


#include<iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
int N,K;
int hash[1000002];
bool flag[1000002];
int num[5002];

int main()
{
	
	while (cin >> N >> K)
	{
		//Prime();
		int mN = 0;
		for (int i = 0; i < N; ++ i)
		{
			cin >> num[i];
			for (int j = 0; j < i; ++ j)
			{
				int x = num[i] - num[j];
				if (x < 0)
				{
					x = -x;
				}
				hash[x]++;
				mN = max(mN,x);
			}
		}

		int hm = K*(K+1)>>1;
		
		for (int i = N-K;;++i)
		{
			int tmp = 0;
			for (int j = i; j <= mN && ((tmp+=hash[j]) <= hm); j += i)
			{
			}
			if (tmp <= hm)
			{
				tmp = 0;
				memset(flag,0,sizeof(flag));
				for (int j = 0; j < N; ++ j)
				{
					if (tmp  > K)
					{
						break;
					}
					if (flag[num[j]%i])
					{
						tmp ++;
					}
					else
						flag[num[j]%i] = 1;
				}
			}
			if (tmp <= K)
			{
				cout << i << endl;
				break;
			}
		}
	}
	return 0;
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值