您的位置:首页 > 其它

【NOIP提高组模拟A组8.15】膜法师 (Standard IO)

2017-08-15 20:42 471 查看

题目大意:

一个序列A[i],你要把它构成一个B序列,满足length(B)+K>=length(A),a[i]-k<=B[i]<=a[i]让他们有一个公因数G,输出所有的G。

50 n<=1000;

90 n<=100000;

100 n<=2000000

思路:

50分暴力就好了,每次枚举一个是是否可以是G的倍数。

90和100是同一个算法,但是90是pascal,100是C++(Pascal没人对!!!!)。

思路是可以把它转化成一个区间上的问题,就是问对于枚举的每一个G他的G到G-K,2*G到2*G-K….一直到max(a[i]) div G这里面有多少个数。时间复杂度是(max(a[i])*ln(maxa[i]));一般都是算成(max(a[i])*log(max(a[i])));

这题的结题思路就是转化成区间去思考,不过pascal就很惨了。代码30行左右,真的特别好打

程序:

uses math;
const
maxn=2000000;
var
f,a,b:array [-maxn..maxn] of longint;
i,j,t,ii,n,m,k,ans,g,cmax:longint;
begin
readln(t);
for ii:=1 to t do
begin
readln(n,m,k);
for i:=1 to n do
begin
read(a[i]);
a[i]:=a[i]-m;
inc(b[a[i]]);
if a[i]>cmax then cmax:=a[i];
end;
for i:=-maxn+1 to maxn do
f[i]:=f[i-1]+b[i];

for i:=1 to cmax do
begin
if i<=m then
begin
if f[i-m-1]<=k then write(i,' ');
continue;
end;
ans:=f[i]-f[i-m-1];
g:=i;
for j:=2 to (cmax div i)+1 do
begin
ans:=ans+f[j*i]-f[max(j*i-m-1,g)];
g:=g+i;
end;
if n-ans<=k then write(i,' ');
end;
writeln;
if ii=t then break;
fillchar(b,sizeof(b),0);
fillchar(f,sizeof(f),0);
end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  何嘉阳