zoukankan      html  css  js  c++  java
  • 【29.27%】【hdu 5908】Abelian Period

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/131072 K (Java/Others)
    问题描述
    设SS是一个数字串,定义函数occ(S,x)occ(S,x)表示SS中数字xx的出现次数。

    例如:S=(1,2,2,1,3),occ(S,1)=2,occ(S,2)=2,occ(S,3)=1S=(1,2,2,1,3),occ(S,1)=2,occ(S,2)=2,occ(S,3)=1。

    如果对于任意的ii,都有occ(u,i)=occ(w,i)occ(u,i)=occ(w,i),那么我们认为数字串uu和ww匹配。

    例如:(1,2,2,1,3)approx(1,3,2,1,2)(1,2,2,1,3)≈(1,3,2,1,2)。

    对于一个数字串SS和一个正整数kk,如果SS可以分成若干个长度为kk的连续子串,且这些子串两两匹配,那么我们称kk是串SS的一个完全阿贝尔周期。

    给定一个数字串SS,请找出它所有的完全阿贝尔周期。
    输入描述
    输入的第一行包含一个正整数T(1leq Tleq10)T(1≤T≤10),表示测试数据的组数。

    对于每组数据,第一行包含一个正整数n(nleq 100000)n(n≤100000),表示数字串的长度。

    第二行包含nn个正整数S_1,S_2,S_3,…,S_n(1leq S_ileq n)S
    ​1
    ​​ ,S
    ​2
    ​​ ,S
    ​3
    ​​ ,…,S
    ​n
    ​​ (1≤S
    ​i
    ​​ ≤n),表示这个数字串。
    输出描述
    对于每组数据,输出一行若干个整数,从小到大输出所有合法的kk。
    输入样例
    2
    6
    5 4 4 4 5 4
    8
    6 5 6 5 6 5 5 6
    输出样例
    3 6
    2 4 8

    【题解】

    可以知道这个周期k一定是n的一个因数。
    所谓的两两相同。其实就是全都相同。
    涉及到两个“集合”是否相同的判断.
    做法是
    把第一个集合里面的元素全都加到平衡树里面。
    然后第二个集合里面。遇到一个元素就尝试在平衡树里面删除掉这个元素。
    如果发现没有这个元素就表示不相同。
    最后如果平衡树不为空也不相同。
    以上判断都做完之后就可以判断两个集合是相同的了。
    我们不必写一个平衡树。用现成的map即可。
    枚举k
    nextj..nextj+k-1.代表一段区间。
    和1..k区间比较是否”相同即可”;
    如果一个元素的map值为0了。就要erase掉。
    这样才能用empty()函数判断map是否为空。

    #include <cstdio>
    #include <map>
    
    using namespace std;
    const int MAXN = 101000;
    
    int t,n,a[MAXN];
    map <int,int> dic;
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        scanf("%d", &t);
        while (t--)
        {
            bool flag = false;
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            for (int k = 1;k <= n;k++)
                if ((n%k) == 0)
                {
                    int j = 1;
                    int nextj = 1 + k;
                    bool judge = true;
                    while (nextj <= n)
                    {
                        dic.clear();
                        for (int l = 1; l <= k; l++)
                            dic[a[l]]++;
                        for (int l = nextj; l <= nextj + k - 1; l++)
                        {
                            dic[a[l]]--;
                            if (dic[a[l]] == 0)
                                dic.erase(a[l]);
                        }
                        if (!dic.empty())
                        {
                            judge = false;
                            break;
                        }
                        nextj += k;
                    }
                    if (judge)
                    {
                        if (!flag)
                            printf("%d", k);
                        else
                            printf(" %d", k);
                        flag = true;
                    }
                }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    虚拟机中Linux 下安装tools
    各个复位标志解析,让我们对MCU的程序的健康更有把控
    用过的两种鼠标右键添加快捷指令方法
    一个ftp协议传输文件之后执行脚本无法工作的情况
    一文入门Linux下gdb调试(二)
    一文入门Linux下gdb调试(一)
    VS CODE远程办公篇一
    Kwp2000协议的应用(程序后续篇)
    Kwp2000协议的应用(程序原理篇)
    Kwp2000协议的应用(硬件原理使用篇)
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632199.html
Copyright © 2011-2022 走看看