I and OI
Past...

题意:Given an integer N(1<N<2^31),you are to calculate ∑gcd(i, N) 1<=i<=N.

分析:数论题的魅力就在于此,一道题就一句简单的描述.

显然,最后的答案肯定是由N的约数组成的,于是我们试着统计每个约数被用了几次.

对于N的一个约数D,有多少个数与N的gcd是D呢?答案是φ(N/D).

于是ans=∑φ(N/D)*D==∑φ(D)*(N/D). (D为N的约数)

效率为O(sqrt(N)).

code:

var   p,cnt:array[0..15] of longint;
      n,m,num,i:longint;
      tmp,ans:extended;

      procedure dfs(now:extended; k:longint);
      var   x,y:longint;
      begin
            if k>m then
            begin
                  ans:=ans+now*n;
                  exit;
            end;

            for x:=0 to cnt[k] do
            begin
                  if x<>0 then now:=now*(1-1/p[k]);
                  dfs(now,k+1);
                  if x<>0 then now:=now/(1-1/p[k]);
            end;
      end;

begin
      while not seekeof do
      begin
            readln(n);
            num:=n;
            m:=0;
            fillchar(cnt,sizeof(cnt),0);
            for i:=2 to trunc(sqrt(n)) do
               if num mod i=0 then
               begin
                     inc(m);
                     p[m]:=i;
                     while num mod i=0 do
                     begin
                           inc(cnt[m]);
                           num:=num div i;
                     end;
                     if num=1 then break;
               end;
            if num>1 then
            begin
                  inc(m);
                  p[m]:=num;
                  cnt[m]:=1;
            end;
            ans:=0;
            dfs(1,1);
            writeln(ans:0:0);
      end;
end.
posted on 2011-08-13 13:18  exponent  阅读(347)  评论(0编辑  收藏  举报