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
学了一种新的求欧拉函数的筛法——欧拉筛法
代码:
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.
又作了一个小优化,缩小了空间使用,去掉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.