[JZOJ 4699][CF583C]【NOIP2016提高A组模拟8.15】Password
2016-08-16 16:55
513 查看
Description
Input
Output
Sample Input
4
1 1 2 2 3 4 6 2 2 1 3 2 2 1 3 2
Sample Output
6 4 3 2
在于矩阵中的。有一个显然的性质就是 Gcd(a,b) <= a、b,我们设还原后的
序列从大到小排序后为 B数组。那么 B[1]一定就是矩阵中最大的数,
B[2]一定是矩阵中第二大的数。考虑 B[3]是否也满足这个性质。我发现
矩阵中可能比他大的就只有 Gcd(B[1],B[2])。那么每取出一个 B[i],
把 B[i]以及与 B[1~i-1]的 Gcd去掉后,后面的数取最大就可以了。
gcd要去掉2个。因为这矩阵是对称的。
那怎样删除这些数字了?
我们需要二分来查找gcd(a,b)
我们知道在排序之后,所有相同的数都会堆在一起。
那么,我们就可以在每一种数第一次出现的地方,
记录题目已经用了几个。
这里说明一下lower_bound好像只能在升序序列上用…
Input
Output
Sample Input
4
1 1 2 2 3 4 6 2 2 1 3 2 2 1 3 2
Sample Output
6 4 3 2
The Solution
首先,序列中的数对应的就是 Gcd 矩阵中对角线的数字,所以一定是存在于矩阵中的。有一个显然的性质就是 Gcd(a,b) <= a、b,我们设还原后的
序列从大到小排序后为 B数组。那么 B[1]一定就是矩阵中最大的数,
B[2]一定是矩阵中第二大的数。考虑 B[3]是否也满足这个性质。我发现
矩阵中可能比他大的就只有 Gcd(B[1],B[2])。那么每取出一个 B[i],
把 B[i]以及与 B[1~i-1]的 Gcd去掉后,后面的数取最大就可以了。
gcd要去掉2个。因为这矩阵是对称的。
那怎样删除这些数字了?
我们需要二分来查找gcd(a,b)
我们知道在排序之后,所有相同的数都会堆在一起。
那么,我们就可以在每一种数第一次出现的地方,
记录题目已经用了几个。
这里说明一下lower_bound好像只能在升序序列上用…
CODE
#include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #define fo(i,a,b) for (int i=a;i<=b;i++) #define fd(i,a,b) for (int i=a;i>=b;i--) #define N 1005 using namespace std; int a[N*N],wz[N*N],b ; int n; inline int read() { int x=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*w; } bool cmp(int x,int y) {return x>y;} int gcd(int x,int y) {return x%y==0?y:gcd(y,x%y);} int find(int x) { int l=3,r=n*n; while (l<r) { int mid=(l+r)>>1; if (a[mid]>x) l=mid+1; else r=mid; } return l; } int main() { freopen("password1.in","r",stdin); freopen("password.out","w",stdout); n=read(); fo(i,1,n*n) { a[i] = read(); wz[i] = i; } sort(a+1,a+1+n*n,cmp); b[1] = a[1]; b[2] = a[2]; //int Pos=lower_bound(a+3,a+n*n+1,gcd(b[1],b[2]))-a; int Pos=find(gcd(b[1],b[2])); wz[Pos]+=2; int x=3; fo(i,3,n) { while (a[wz[x]]!=a[x]) x=wz[x]; b[i]=a[x]; // int k=lower_bound(a+3,a+n*n+1,b[i])-a; int k=find(b[i]); wz[k]++; fo(j,1,i-1) { int Pos=find(gcd(b[i],b[j])); // int Pos=lower_bound(a+3,a+n*n+1,gcd(b[i],b[j]))-a; wz[Pos]+=2; } } fo(i,1,n) printf("%d ",b[i]); }
相关文章推荐
- JZOJ 4699 Password【NOIP2016提高A组模拟8.15】
- Password【NOIP2016提高A组模拟8.15】
- 【NOIP2016提高A组模拟8.15】Password
- 【NOIP2016提高A组模拟8.15】Password
- 【NOIP2016提高A组模拟8.15】Password
- JZOJ.4699【NOIP2016提高A组模拟8.15】Password
- JZOJ 4711. 【NOIP2016提高A组模拟8.17】Binary
- 【JZOJ4799】【NOIP2016提高A组模拟9.24】我的快乐时代
- 【JZOJ4805】【NOIP2016提高A组模拟9.28】跟踪
- JZOJ 4726. 【NOIP2016提高A组模拟8.22】种花
- JZOJ5279. 【NOIP提高组模拟A组8.15】香港记者
- JZOJ 4821. 【NOIP2016提高A组模拟10.15】打膈膜
- JZOJ4675. 【NOIP2016提高A组模拟7.21】Double-row
- 【JZOJ4715】【NOIP2016提高A组模拟8.19】树上路径
- JZOJ 4693 疯狂的火神【NOIP2016提高A组模拟8.14】
- Throw 【NOIP2016提高A组模拟8.15】
- 【jzoj5280】【NOIP提高组模拟A组8.15】【膜法师】
- JZOJ 4629 修路【NOIP2016提高A组模拟7.15】
- JZOJ 100024. 【NOIP2016提高A组模拟7.6】数球