HDU 5908 Abelian Period 可以直接用multiset

Posted stupid_one

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5908 Abelian Period 可以直接用multiset相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=5908

要求把数组分成k组使得每组中的元素出现次数相同

就是分成k个集合,那么直接用multiset判定就可以

有重载相等运算符的

我被坑了的就是,

对于2个元素一个集合的可以,那么,4,6,8这样分集合也是可以的。

这个很容易理解

但是,你也要能平均分才行啊

就是10的2可以,但是4是一定不可以得。不能平均分

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 100000 + 20;
int a[maxn];
multiset<int>aa;
multiset<int>bb;
set<int>ans;
void work() {
    aa.clear();
//    bb.clear();
    ans.clear();
    int n;
    scanf("%d", &n);
    bool flag = true;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        if (i >= 2 && a[i] != a[i - 1]) flag = false;
    }
    ans.insert(n);
    if (flag) {
        for (int i = 1; i <= n / 2; ++i) {
            if (n % i == 0) {
                ans.insert(i);
            }
        }
    } else {
        int begin = 1, end = -1;
        for (int i = 2; i <= n / 2; ++i) {
            if (n % i != 0) continue;
            if (ans.find(i) != ans.end()) continue;
//            aa.clear();
            end = i;
//            cout << begin << " " << end << " " << i << endl;
            for (int j = begin; j <= end; ++j) {
                aa.insert(a[j]);
            }
            begin = end + 1;
            flag = true;
            for (int j = 2 * i; j <= n; j += i) {
                bb.clear();
                for (int k = j; k >= j - i + 1; --k) {
                    bb.insert(a[k]);
                }
                if (aa != bb) {
                    flag = false;
                    break;
                }
            }
            if (!flag) continue;
            for (int j = i ; j <= n / 2; j += i) {
                if (n % j == 0) //10的2不代表10的4
                    ans.insert(j);
            }
        }
    }
//    show();
    set<int> :: iterator it = ans.begin();
    printf("%d", *it);
    it++;
    for (; it != ans.end(); ++it) {
        printf(" %d", *it);
    }
    printf("\\n");
    return;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    int t;
    scanf("%d", &t);
    while(t--) work();
    return 0;
}
View Code

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 100000 + 20;
int a[maxn];
bool isok[maxn];
int n;
int cnt[maxn];
int cmp[maxn];
bool check(int val) {
    for (int i = 1; i <= val; ++i) {
        cnt[a[i]] = 0;
    }
    for (int i = 1; i <= val; ++i) {
        cnt[a[i]]++;
    }
    for (int i = 2 * val; i <= n; i += val) {
        for (int j = i; j >= i - val + 1; --j) {
            cmp[a[j]] = 0;
        }
        for (int j = i; j >= i - val + 1; --j) {
            cmp[a[j]]++;
        }
        for (int j = 1; j <= val; ++j) {
            if (cnt[a[j]] != cmp[a[j]]) return false;
        }
    }
    return true;
}
void work() {
    scanf("%d", &n);
    bool flag = true;
    memset(isok, 0, sizeof isok);
    isok[n] = 1;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        if (i >= 2 && a[i] != a[i - 1]) flag = false;
    }
    if (flag) {
        for (int i = 1; i <= n / 2; ++i) {
            if (n % i == 0) {
                isok[i] = 1;
            }
        }
    } else {
        for (int i = 2; i <= n / 2; ++i) {
            if (n % i != 0 || isok[i]) continue;
            if (check(i)) {
                for (int j = i; j <= n / 2; ++j) {
                    if (n % j == 0) isok[i] = 1;
                }
            }
        }
    }
    flag = 0;
    for (int i = 1; i <= n; ++i) {
        if (isok[i]) {
            if (!flag) {
                printf("%d", i);
                flag = 1;
            } else {
                printf(" %d", i);
            }
        }
    }
    printf("\\n");
    return;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    int t;
    scanf("%d", &t);
    while(t--) work();
    return 0;
}

 

以上是关于HDU 5908 Abelian Period 可以直接用multiset的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5908 Abelian Period (暴力)

HDU 5908 Abelian Period 可以直接用multiset

Abelian Period

HDU 1358 Period

hdu 1358 period KMP入门

Period HDU - 1358