bzoj 2190 线性生成欧拉函数表

首先我们知道,正方形内个是对称的,关于y=x对称,所以只需要算出来一半的人数

然后乘2+1就行了,+1是(1,1)这个点

开始我先想的递推

那么我们对于一半的三角形,一列一列的看,假设已经求好了第I-1列的,那么第I列加上

之后,不会影响前I-1列能看见的人,那么第I列一共加上I个人,设坐标是(I,Y),

我们可以发现如果gcd(I,Y)<>1的时候这个点是看不见的,因为横纵坐标存在约数,也就是

前面有一个整点点和这个点还有原点在同一直线上(三角形相似),那么我们要找第I列I,Y互质的

点,也就是和I互质的点的个数,也就是phi(i),那么就不用递推了,我们每个I都要累加phi,也就是

生成1-n-1的欧拉函数表就行了(n-1是因为(0,0)点算第1列,我就在这儿WA了一次。。。)

/**************************************************************
    Problem: 2190
    User: BLADEVIL
    Language: Pascal
    Result: Accepted
    Time:28 ms
    Memory:696 kb
****************************************************************/
 
//By BLADEVIL
var
    i, j                        :longint;
    n                           :longint;
    phi, mindiv                 :array[0..40100] of longint;
    prime                       :array[0..40000] of longint;
    ans                         :int64;
     
begin
    read(n);
    for i:=2 to n do
    begin
        if mindiv[i]=0 then
        begin
            mindiv[i]:=i;
            inc(prime[0]);
            prime[prime[0]]:=i;
            phi[i]:=i-1;
        end;
        for j:=1 to prime[0] do
        begin
            if prime[j]*i>n then break;
            if i mod prime[j]<>0 then
                phi[i*prime[j]]:=phi[i]*(prime[j]-1) else
                phi[i*prime[j]]:=phi[i]*prime[j];
            mindiv[prime[j]*i]:=prime[j];
            if i mod prime[j]=0 then break;
        end;
    end;
    phi[1]:=1;
    for i:=1 to n-1 do ans:=ans+phi[i];
    ans:=ans*2+1;
    writeln(ans);
end.

 

 

 

posted on 2013-12-11 23:22  BLADEVIL  阅读(383)  评论(0编辑  收藏  举报