Password【NOIP2016提高A组模拟8.15】
2016-08-15 20:37
316 查看
题目
样例输入:
4
1 1 2 2 3 4 6 2 2 1 3 2 2 1 3 2
样例输出:
6 4 3 2
数据范围:
剖解题目
有一个N位B数组,经过一个公式得到了N*N的A数组,现将A数组打乱,让你找回B数组。思路
应该仔细研究两个数组之间的关系,没有其他想法了吧…….解法
20%:因为所有的数都是互质的,只需要把gcd不是1的数拿出来,然后排个序输出。?%:会发现,这N个数中,每两个数都会是A数组中两个位置的答案,每个数对应着一个位置,只需要将A数组中,出现次数为奇数的拿出来,排序输出。
?%:有人水了90分,表示这分来历不明不懂。
100%:其实这N*N个数就是对应着一个矩阵,这个矩阵沿着对角线对称,对角线上的数就是答案。
显然,最大的数一定是答案的第一个,第二大的数也是答案第二个,第三个还是吗?我们发现比第三个大的数除去第一第二以外,只有可能是第一个与第二个数的gcd,那么如果这个gcd不等于第三个的话,那第三个就是答案之一。
所以,我们每次从A数组(已经排好序),取出一个数A[i],我们把我们的ans数组中每个与A[i]的gcd在A数组中都删掉,而且要删两次(因为每两个数是对应这A数组中的两个位置),再选择A数组中剩下的最大值即可。
然而,a[i]<=109,桶肯定不行,我们需要用到hash等一些列可离散化的东西,作为一名C++选手,就偷懒的用了map了。
代码
#include<map> #include<cstdio> #include<algorithm> #include<functional> #include<cstdlib> #include<cstring> #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=1005,maxnn=1000005; int n,ans[maxn],a[maxnn]; map<int,int> cy; int gcd(int x,int y) { if (!y) return x; else return gcd(y,x%y); } int main() { freopen("T.in","r",stdin); scanf("%d",&n); fo(i,1,n*n) { scanf("%d",&a[i]); cy[a[i]]++; } sort(a+1,a+n*n+1,greater<int>()); ans[++ans[0]]=a[1]; fo(i,2,n*n) if (cy[a[i]]>0){ fo(j,1,ans[0]){ int x=gcd(a[i],ans[j]); cy[x]-=2; } if (cy[a[i]]>0) { ans[++ans[0]]=a[i]; cy[a[i]]--; } if (ans[0]==n) break; } fo(i,1,ans[0]) printf("%d ",ans[i]); }
相关文章推荐
- 【NOIP2016提高A组模拟8.15】Password
- 【NOIP2016提高A组模拟8.15】Password
- [JZOJ 4699][CF583C]【NOIP2016提高A组模拟8.15】Password
- JZOJ.4699【NOIP2016提高A组模拟8.15】Password
- JZOJ 4699 Password【NOIP2016提高A组模拟8.15】
- 【NOIP2016提高A组模拟8.15】Password
- Throw 【NOIP2016提高A组模拟8.15】
- 【NOIP2016提高A组模拟8.15】Throw(BZOJ2144)
- 【NOIP2016提高A组模拟8.15】Throw
- 【NOIP2016提高A组模拟8.15】Garden
- [JZSC2016 Part 2]【NOIP2016提高A组模拟8.15】总结
- 【NOIP2016提高A组模拟8.15】Garden
- 【NOIP2016提高A组模拟8.15】Throw
- JZOJ.4701【NOIP2016提高A组模拟8.15】Throw
- CQOI2012 BZOJ2669 【NOIP2016提高A组模拟8.15】Garden
- 【NOIP2016提高A组模拟8.17】(雅礼联考day1)Binary
- JZOJ 100024. 【NOIP2016提高A组模拟7.6】数球
- JZOJ.4715【NOIP2016提高A组模拟8.19】树上路径