51nod1217
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1217相关的知识,希望对你有一定的参考价值。
给你n个数和k,表示你可以从这n个数中去掉k个,你现在要确定一个最小的m,使得剩下的n-k个数在模m下不同余。(n <= 5000, k <= 4, a[i] <= 1e6)
预处理出任意两个数的差,用cnt[u]记录有多少对的差为u,则模m下同余的对数 = cnt[0] + cnt[m] + cnt[2 * m] + cnt[3 * m] + ...
从小到大枚举m,当模m下同余的对数 > k * (k + 1) / 2时显然无解,否则把这些同余的数字挑出来,看要去掉几个数字,和k比较,看m是否合适
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> using namespace std; #define rep(i, j, k) for (int i = int(j); i <= int(k); ++ i) typedef pair<int, int> P; const int N = 5007; const int M = 1e6 + 7; int a[N]; int cnt[M]; int n, k, K; struct Node { int v; int next; }e[(int)1.3e7]; int head[M], tot = 0; int vis[M]; inline void add(int u, int i, int j) { tot ++; e[tot].v = 5010 * i + j; e[tot].next = head[u]; head[u] = tot; } inline bool ok(int m) { int sum = 0; for (int i = 0; i < M; i += m) sum += cnt[i]; if (sum > K) return 0; vector<int> v; for (int i = 0; i < M; i += m) if (cnt[i]) { for (int j = head[i]; j; j = e[j].next) { v.push_back(e[j].v % 5010); v.push_back(e[j].v / 5010); } } sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); for (int i = 0; i < v.size(); ++ i) vis[a[v[i]] % m] = 0; int num = 0; for (int i = 0; i < v.size(); ++ i) { if (vis[a[v[i]] % m]) num ++; else vis[a[v[i]] % m] = 1; } if (num <= k) return 1; return 0; } int main() { scanf("%d%d", &n, &k); K = k * (k + 1) / 2; rep(i, 1, n) scanf("%d", a + i); rep(i, 1, n) rep(j, i + 1, n) { if (a[i] > a[j]) { cnt[a[i] - a[j]] ++; add(a[i] - a[j], i, j); } else { cnt[a[j] - a[i]] ++; add(a[j] - a[i], i, j); } } for (int i = n - k; ; ++ i) if (ok(i)) { printf("%d\n", i); return 0; } }
以上是关于51nod1217的主要内容,如果未能解决你的问题,请参考以下文章
51nod 1217 Minimum Modular(数论+暴力)