【NOIP2016练习】T3 质数 (分块)

题意:共有N盏灯,标号为1N,有M个标有不同质数的开关,开关可以控制所有标号为其标号倍数的灯,按一次开关,所有其控制的灭着的灯都点亮,所有其控制的亮着的灯将熄灭。现在,宿管可以无限的按所有开关,所有灯初始状态为熄灭,请求出最多能点亮几盏灯。

 

对于100%的数据,T<=10,N<=1000 所有标号不相等,MN以内的质数总个数。

思路:分块,将<=sqrt(n)的质数分成一份共有N1个,另一份共有N2个。

    对于第一部分因为n<=1000则N1<=11,可以用暴力枚举+标记存储亮灭情况

    对于第二部分因为b[i]>sqrt(n)则第二部分开关之间互不影响,只与第一部分有关,具有贪心性质

 

 1 var a,b,c:array[1..2000]of longint;
 2     n,m,cas,v,i,x,ans,n1,n2:longint;
 3 
 4 procedure dfs(k:longint);
 5 var t,tmp,i,j:longint;
 6 begin
 7  if k=n1+1 then
 8  begin
 9   t:=0;
10   for i:=1 to n do t:=t+c[i];
11   for i:=1 to n2 do
12   begin
13    tmp:=0;
14    for j:=1 to n div b[i] do
15     if c[b[i]*j]=1 then dec(tmp)
16      else inc(tmp);
17    if tmp>0 then
18    begin
19     t:=t+tmp;
20     for j:=1 to n div b[i] do c[b[i]*j]:=1-c[b[i]*j];
21    end;
22   end;
23   if t>ans then ans:=t;
24   exit;
25  end;
26  dfs(k+1);
27  for i:=1 to n div a[k] do c[i*a[k]]:=1-c[i*a[k]];
28  dfs(k+1);
29  for i:=1 to n div a[k] do c[i*a[k]]:=1-c[i*a[k]];
30 end;
31 
32 begin
33  assign(input,'prime.in'); reset(input);
34  assign(output,'prime.out'); rewrite(output);
35  readln(cas);
36  for v:=1 to cas do
37  begin
38   readln(n,m);
39   n1:=0; n2:=0;
40   for i:=1 to m do
41   begin
42    read(x);
43    if x<=trunc(sqrt(n)) then begin inc(n1); a[n1]:=x; end
44     else begin inc(n2); b[n2]:=x; end;
45   end;
46   ans:=0;
47   fillchar(c,sizeof(c),0);
48   dfs(1);
49   writeln(ans);
50  end;
51  close(input);
52  close(output);
53 end.

 

posted on 2016-10-22 20:06  myx12345  阅读(387)  评论(0编辑  收藏  举报

导航