【NOIP模拟】密码

题面

闲聊

暴力分也给的太少了,刁钻

而且为什么菲鲁特不配拥有姓名??给我菲鲁特宝一个大大的姓名

好了不BB了

第一题都挂我也不配拥有姓名。。

分析

其实你会发现密码串b的gcd会构成一个N*N的gcd矩阵,而对角线上的数字正是b序列

而这个gcd矩阵其实就是未被打乱前的a序列

而又要满足不下降,还有一个很显然的结论 a,b≤gcd(a,b)

因此b[1]一定是矩阵中最大的数(默认数组从1开始编号),b[2]一定是第二大的。(对角线上数的需要满足不上升,所以一定比他们小。而比他们小的数的gcd也比他们小)

那么b[3]是否是第三大呢?不一定。除了b[1]和b[2]之外,只可能b[1]和b[2]的gcd比它大。

因此衍生出去,当我们每次求到一个b[i]后,需要把a序列中的gcd(b[i],b[j])(j≤i)全部删掉(每次删两个),再找到一个最大的作为b[i+1]

因为ai在1e9以内,所以又得用map这坑货

复杂度:O(?2 LogN)

代码

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define N 1010  
  4. #define RT register  
  5. int n,n2,cnt;  
  6. int a[N*N],b[N],ans[N],bc[N];  
  7. map<int,int>mp;  
  8. template<class T>  
  9. inline void read(T &x)  
  10. {  
  11.     x=0;int f=1;static char ch=getchar();  
  12.     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  
  13.     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  
  14.     x*=f;  
  15. }  
  16. inline int gcd(int a,int b){return b?gcd(b,a%b):a;}  
  17. int main()  
  18. {  
  19.     read(n);n2=n*n;  
  20.     for(RT int i=1;i<=n2;++i)read(a[i]),mp[a[i]]++;  
  21.     sort(a+1,a+1+n2);  
  22.     for(RT int i=n2;i>=1;i--)  
  23.         while(mp[a[i]])  
  24.         {  
  25.             ans[++cnt]=a[i];mp[a[i]]--;  
  26.             for(int j=1;j<cnt;j++)  mp[gcd(a[i],ans[j])]-=2;  
  27.         }  
  28.     for(RT int i=1;i<=n;++i)printf("%d ",ans[i]);  
  29.     return 0;  
  30. }  

转载于:https://www.cnblogs.com/NSD-email0820/p/9869632.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值