SDOI2008仪仗队

这题应该注意到与b2818的不同

一个点能被看见当且仅当它与(1,1)的横纵坐标的距离gcd为1

所以问题转化为x,y<=n-1,求gcd(x,y)=1的方案数

最后要加上2

代码:

 1 var i,n,tot:longint;
 2     ans:int64;
 3     phi:array[0..50000] of int64;
 4     p:array[0..50000] of longint;
 5 procedure get;
 6  var i,j:longint;
 7    begin
 8      fillchar(phi,sizeof(phi),0);
 9      tot:=0;
10      phi[1]:=0;
11      for i:=2 to n do
12       if phi[i]=0 then
13        begin
14          phi[i]:=i-1;inc(tot);p[tot]:=i;
15          j:=i+i;
16          while j<=n do
17            begin
18              if phi[j]=0 then phi[j]:=j;
19              phi[j]:=(phi[j] div i)*(i-1);
20              inc(j,i);
21            end;
22        end;
23    end;
24 procedure main;
25  begin
26    readln(n);dec(n);
27    get;
28    for i:=2 to n do inc(phi[i],phi[i-1]);
29    writeln(2*phi[n]+3);
30  end;
31 begin
32   main;
33 end.
34               
View Code

 学了一种新的求欧拉函数的筛法——欧拉筛法

代码:

 1 var  i,n,tot:longint;
 2      ans:int64;
 3      fai:array[0..50000] of int64;
 4      p:array[0..50000] of longint;
 5      check:array[0..50000] of boolean;
 6 procedure getfai;
 7  var i,j,k:longint;
 8  begin
 9  tot:=0;
10  fillchar(check,sizeof(check),false);
11  for i:=2 to n do
12   begin
13   if not(check[i]) then
14    begin
15     inc(tot);
16     p[tot]:=i;
17     fai[i]:=i-1;
18    end;
19   for j:=1 to tot do
20    begin
21     k:=i*p[j];
22     if k>n then break;
23     check[k]:=true;
24     if i mod p[j]=0 then
25      begin
26       fai[k]:=fai[i]*p[j];
27       break;
28      end
29     else
30       fai[k]:=fai[i]*(p[j]-1);
31    end;
32  end;
33 end;
34 procedure main;
35  begin
36  readln(n);dec(n);
37  getfai;
38  for i:=2 to n do inc(fai[i],fai[i-1]);
39  writeln(2*fai[n]+3);
40  end;
41 begin
42  main;
43 end.          
View Code

 又作了一个小优化,缩小了空间使用,去掉check数组,直接用fai是否为0来判断是否是质数

代码:

 1 var  i,n,tot:longint;
 2      ans:int64;
 3      fai:array[0..50000] of int64;
 4      p:array[0..50000] of longint;
 5 procedure getfai;
 6  var i,j,k:longint;
 7  begin
 8  tot:=0;
 9  fillchar(fai,sizeof(fai),0);
10  for i:=2 to n do
11   begin
12   if fai[i]=0 then
13    begin
14     inc(tot);
15     p[tot]:=i;
16     fai[i]:=i-1;
17    end;
18   for j:=1 to tot do
19    begin
20     k:=i*p[j];
21     if k>n then break;
22     if i mod p[j]=0 then
23      begin
24       fai[k]:=fai[i]*p[j];
25       break;
26      end
27     else
28       fai[k]:=fai[i]*(p[j]-1);
29    end;
30  end;
31 end;
32 procedure main;
33  begin
34  readln(n);dec(n);
35  getfai;
36  for i:=2 to n do inc(fai[i],fai[i-1]);
37  writeln(2*fai[n]+3);
38  end;
39 begin
40  main;
41 end.       
View Code

 

posted @ 2014-06-20 20:17  ZYF-ZYF  Views(192)  Comments(0Edit  收藏  举报