1. 程式人生 > >51nod 1217 Minimum Modular(數論+暴力)

51nod 1217 Minimum Modular(數論+暴力)

black min ack turn sort 中間 mark algo isp

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。
Input示例
5 1
1
2
10
11
12
Output示例
4
——————————————————————————————————————————
跟著tjm大爺寫了一波
首先 根據抽屜原理顯然m>=(
n-K)
那麽我們可以枚舉(n-k)到mx的所有情況
當然這樣肯定會T
怎樣去計算幾個數同余的情況呢
如果v[i]≡v[j](mod m),則有m|(v[i]-v[j]),
因此我們可以n^2預處理一波
每次枚舉到一個m我們可以計算他所有的倍數在 n 個數差中出現的情況(cnt)
如果cnt>=(k+1)*k/2 那麽至少有k+1個數同余(這是最壞情況下)
加了這樣一波剪枝之後就完全可以AC辣
技術分享

一開始數組開小T了(我居然不知道o2下數組開小了會T QAQ) 改了一波之後還是蠻快的2333
技術分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using
namespace std; const int M=1e5+7,N=1000007; int read(){ int ans=0,f=1,c=getchar(); while(c<0||c>9){if(c==-) f=-1; c=getchar();} while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();} return ans*f; } int n,k,mx,v[M],vis[N],f[N]; int main() { n=read(); k=read();
if(n+1<=k) return puts("1"),0; for(int i=1;i<=n;i++) v[i]=read(),mx=max(mx,v[i]); sort(v+1,v+1+n); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) f[v[j]-v[i]]++; for(int i=n-k;i<=mx;i++){ int cnt=0; for(int j=1;i*j<=mx;j++) cnt+=f[i*j]; if(cnt>(k*(k+1)>>1)) continue; cnt=0; for(int j=1;j<=n;j++){ int now=v[j]%i; if(vis[now]!=i) vis[now]=i; else cnt++; } if(cnt<=k) return printf("%d\n",i),0; } return 0; }
View Code

 

51nod 1217 Minimum Modular(數論+暴力)