hdu 5908 Abelian Period(暴力 + map优化)
来源:互联网 发布:反屏蔽器软件 编辑:程序博客网 时间:2024/05/22 13:37
Abelian Period
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/131072 K (Java/Others)
Problem Description
Let S be a number string, and occ(S,x) means the times that number x occurs in S.
i.e. S=(1,2,2,1,3),occ(S,1)=2,occ(S,2)=2,occ(S,3)=1.
String u,w are matched if for each number i, occ(u,i)=occ(w,i) always holds.
i.e. (1,2,2,1,3)≈(1,3,2,1,2).
Let S be a string. An integer k is a full Abelian period of S if S can be partitioned into several continous substrings of length k, and all of these substrings are matched with each other.
Now given a string S, please find all of the numbers k that k is a full Abelian period of S.
Input
The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.
In each test case, the first line of the input contains an integer n(n≤100000), denoting the length of the string.
The second line of the input contains n integers S1,S2,S3,…,Sn(1≤Si≤n), denoting the elements of the string.
Output
For each test case, print a line with several integers, denoting all of the number k. You should print them in increasing order.
Sample Input
2
6
5 4 4 4 5 4
8
6 5 6 5 6 5 5 6
Sample Output
3 6
2 4 8
把一个长为n的数组切成i段,这i段都要满足以下条件:
1.每一段的长度相同;
2.每一段中的某个数字的出现次数要两两相同;
求所有可能的切割方案,并输出每个方案的n / i.
题目本身不难,思路也很耿直,枚举k(1~n的整数),若是n的约数就直接把数组平均切成k段,判断每一段各个数字的出现次数是否相等即可,理论上时间复杂度可以过。
然而一开始记录是开的数组,由于memset的存在,时间死活压不下来,最后用map才搞定(事实上使用map也是这道题卡时间的关键)。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <map>#include <cmath>#define MAX 100010#define M 100005#define INF 0x3f3f3f3f#define PI acos(-1.0)#define eps 1e-8using namespace std;int arr[M];map<int, int> cmp, tmp;int main(){ int T, n; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%d", &arr[i]); int i = n, a, k, j; for(; i > 0; i--) { if(n % i) continue; cmp.clear(); k = n / i; for(j = 0; j < k; j++) { cmp[arr[j]]++; } tmp = cmp, a = 0; for(; j < n - k + 1; j += k) { tmp = cmp; for(a = j; a < j + k; a++) { if(--tmp[arr[a]] < 0)//如果中间有的数字多出来就跳出循环 break; } if(tmp[arr[a]] < 0)//同上 break; } if(tmp[arr[a]] && tmp[arr[a]] < 0)//同上,进行下一循环 continue; printf("%d", k); i--; break; } for(; i > 0; i--)//只是为了保证输出格式写成这样,上下两段循环里的内容是一样的。 { if(n % i) continue; k = n / i; cmp.clear(); for(j = 0; j < k; j++) { cmp[arr[j]]++; } tmp = cmp, a = 0; for(; j < n - k + 1; j += k) { tmp = cmp; for(a = j; a < j + k; a++) { if(--tmp[arr[a]] < 0) break; } if(tmp[arr[a]] < 0) break; } if(tmp[arr[a]] && tmp[arr[a]] < 0) continue; printf(" %d", k); }printf("\n"); } return 0;}
运行结果:
- hdu 5908 Abelian Period(暴力 + map优化)
- HDU 5908 Abelian Period (暴力+map)
- HDU -- 5908 Abelian Period 【思维 + map + 暴力】
- 【HDU 5908 || #bestcoder88 1002】【map的应用 暴力】Abelian Period
- hdu 5908 Abelian Period【思维+暴力枚举】
- HDU 5908 Abelian Period(暴力)
- HDU-5908-Abelian Period(暴力)
- 【HDU 5908 Abelian Period】
- HDU 5908 Abelian Period
- HDU 5908 Abelian Period
- 【29.27%】【hdu 5908】Abelian Period
- hdu 5908 Abelian Period (枚举)
- hdu 5908 Abelian Period 模拟
- HDU-5908 Abelian Period(思维)
- HDU-5908 Abelian Period(思维)
- hdu5908 Abelian Period 暴力 小小小小的优化
- HDU:5908 Abelian Period(水题+技巧)
- HDU 5908 Abelian Period 模拟乱搞
- js爬坑备忘录
- 启动 Eclipse 弹出“Failed to load the JNI shared library jvm.dll
- 深度优先搜索(DFS)
- redis集群搭建
- KeyMouse.exe 全键盘鼠标<键盘党的福利>
- hdu 5908 Abelian Period(暴力 + map优化)
- Codeforces 374 Div2
- 正则表达式验证
- 流程控制语句
- 1.1-Hive入门(Hive系列)
- HDU 2044 一只小蜜蜂
- android端判断手机是否有网,并且无网时跳转到设置界面
- 关于二分查找
- Gym 100917A 类似拓扑 的好题