• bzoj2818gcd


    原理很简单

    题解我就不自己写了……

    做这题的时候,懂得了一个非常重要的转化:求(x, y) = k, 1 <= x, y <= n的对数等于求(x, y) = 1, 1 <= x, y <= n/k的对数!所以,枚举每个质数p(线性筛素数的方法见:线性时间内筛素数和欧拉函数),然后求(x, y) = 1, 1 <= x, y <= n/p的个数。

    (x, y) = 1的个数如何求呢?其实就是求互质的数的个数。在[1, y]y互质的数有phi(y)个,如果我们令x < y,那么答案就是sigma(phi(y))。因为x, y是等价的,所以答案*2,又因为(1, 1)只有一对,所以-1。最终答案为sigma(sigma(phi(n/prime[i])) * 2 - 1)

    提交的时候我都快疯了

    在这个题中,我们应该需要注意两点:

    一、bzoj上215错误会被报为wa,坑爹啊

    二、在数组开的很大的情况下,能不用int64的就不用

          因为内存占用过大会大致速度变慢

    代码:

     1 var i,n,tot:longint;
     2     ans:int64;
     3     phi:array[0..10000000] of int64;
     4     p:array[0..10000000] 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);
    27    get;
    28    for i:=2 to n do inc(phi[i],phi[i-1]);
    29    ans:=0;
    30    for i:=1 to tot do inc(ans,2*phi[n div p[i]]+1);
    31    writeln(ans);
    32  end;
    33 begin
    34   main;
    35 end.
    36              
    View Code

    (我习惯把phi[1]定为0,因为这比较符合逻辑。)

  • 相关阅读:
    20201022-1 每周例行报告
    2020高级软件工程“领跑衫”获奖感言
    20201015-3 每周例行报告
    20201008-1 每周例行报告
    竞拍作业
    20201207-总结-作业
    20201126-1每周例行报告
    20201120-1每周例行报告
    20201112 -1每周例行报告
    20201105-1例行报告
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3800065.html
Copyright © 2020-2023  润新知