您的位置:首页 > 其它

JZOJ 4699 Password【NOIP2016提高A组模拟8.15】

2016-08-16 11:45 477 查看

Password

题目大意









请你求出密码序列B。

数据范围



题解

这一题比较好玩,如果想得出来,就很简单,否则就很难。

首先将A序列从大到小排序,Ans1=A1,Ans2=A2,这很显然。

现在我们考虑Ans3,Ans3是否就是第三大呢?

我们知道,可能比Ans3大的也就只有gcd(Ans1,Ans2)了。

那我们在找Ans3之前把2个gcd(Ans1,Ans2)从A序列中去掉就行了。

同理,我们找到Ansi后,把两个gcd(Ans1~Ansi−1,Ansi)从序列去掉后,下一个找到的没被去掉Aj的就是Ansi+1。

去掉操作可以用哈希来维护。

Code(Pascal)

const
mo=1000007;
var
n,m,j,k,l,i,o,p:longint;
ans:array[0..2000] of longint;
ha:array[0..1000007,1..2] of int64;
a:array[0..2000000] of int64;
procedure qsort(l,r:longint);
var
i,j:longint;
m:int64;
begin
i:=l;
j:=r;
m:=a[(l+r) div 2];
repeat
while a[i]>m do inc(i);
while a[j]<m do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
function gcd(a,b:int64):int64;
var
t:int64;
begin
t:=0;
repeat
t:=a mod b;
a:=b;
b:=t;
until t=0;
exit(a);
end;
procedure zj(o:longint);
var
m:longint;
begin
m:=o mod mo;
while (ha[m,1]<>0) and (ha[m,1]<>o) do
m:=(m+1) mod mo;
ha[m,1]:=o;
inc(ha[m,2],2);
end;
function ok(o:longint):boolean;
var
m:longint;
begin
m:=o mod mo;
while (ha[m,1]<>0) and (ha[m,1]<>o) do
m:=(m+1) mod mo;
ha[m,1]:=o;
if ha[m,2]=0 then exit(true);
dec(ha[m,2]);
exit(false);
end;
begin
readln(n);
for i:=1 to n*n do
read(a[i]);
qsort(1,n*n);
ans[1]:=a[1];
ans[2]:=a[2];
zj(gcd(ans[1],ans[2]));
k:=2;
for i:=3 to n*n do
if ok(a[i]) then
begin
inc(k);
ans[k]:=a[i];
for l:=1 to k-1 do
zj(gcd(ans[l],ans[k]));
end;
for i:=1 to n do
write(ans[i],' ');
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: