码迷,mamicode.com
首页 > 其他好文 > 详细

51nod1217

时间:2017-10-17 15:25:19      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:algorithm   names   line   pair   int   最小   air   include   同余   

给你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

标签:algorithm   names   line   pair   int   最小   air   include   同余   

原文地址:http://www.cnblogs.com/tempestT/p/7681099.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!