欧拉函数模板 附hdu1286&poj 2407&hdu1787 &hdu2824 【pascal】

关于欧拉函数的讲解不再赘述,直接贴代码


方法一、质因数分解法,对于一个数x,时间复杂度最坏O(n)(当n为质数时)


hdu1286

var
        t,x,ans         :longint;
function find(n:longint):longint;
var
        p:longint;
begin
   ans:=n;p:=2;
   while (n>1) do
   begin
      if n mod p=0 then
      begin
         ans:=ans*(p-1) div p;
         while (n mod p=0) do n:=n div p;
      end;
      inc(p);
   end;
   exit(ans);
end;

begin
   read(t);
   while (t>0) do
   begin
      dec(t);
      read(x);
      writeln(find(x)); 
   end;
end.



poj2407

var
        x,t             :longint;
        ans             :int64;
function find(n:longint):int64;
begin
   t:=2;ans:=n;
   while (n>1) do
   begin
      if n mod t=0 then
      begin
         ans:=ans*(t-1) div t;
         while (n mod t=0) do n:=n div t;
      end;
      inc(t);
   end;
   exit(ans);
end;

begin
   read(x);
   while (x<>0) do
   begin
      writeln(find(x));
      read(x);
   end;
end.



方法二,枚举质因数,对于一个数n,时间复杂度:O(sqrt(n))


hdu 1787

求小于n且不与n互质的数的个数=n-1-phi(n)

var
        ans,x,t          :int64;
function find(n:longint):int64;
var
        p:longint;
begin
   ans:=n;
   for p:=2 to trunc(sqrt(n)) do
   begin
      if n mod p=0 then
      begin
         ans:=ans*(p-1) div p;
         while (n mod p=0) do n:=n div p;
      end;
   end;
   if n>1 then ans:=ans*(n-1) div n;
   exit(ans);
end;

begin
   read(x);
   while (x<>0) do
   begin
      writeln(x-find(x)-1);
      read(x);
   end;
end.


三、线性快速筛欧拉函数 对于范围n  时间复杂度O(n)

就是在快速线性筛质数改了几步:

1.对于筛出来的素数,φ(P)=P-1.

在while循环内

2.若i mod prime[j]=0,那么φ(i*prime[j])=φ(i)*prime[j]

3.若i mod prime[j]≠0,那么φ(i*prime[j])=φ(i)*(prime[j]-1)



hdu2824

var
        eul             :array[0..3000010] of int64;
        vis             :array[0..3000010] of boolean;
        prime           :array[0..217000] of longint;
        ans,t           :int64;
        i               :longint;
        a,b             :longint;
procedure pre_do;
var
        i,j:longint;
begin
   eul[1]:=1;
   for i:=2 to 3000000 do
   begin
      if not vis[i] then
      begin
         inc(t);
         prime[t]:=i;
         eul[i]:=i-1;
      end;
      for j:=1 to t do
       if (prime[j]*i>3000000) then break else
       begin
          vis[i*prime[j]]:=true;
          if (i mod prime[j]<>0) then eul[i*prime[j]]:=eul[i]*eul[prime[j]] else 
          begin
             eul[i*prime[j]]:=eul[i]*prime[j];break;
          end;
       end;
   end;
end;

begin
   pre_do;
   while not eof do
   begin
      readln(a,b);
      ans:=0;
      for i:=a to b do inc(ans,eul[i]);
      writeln(ans);
   end;
end.

——by Eirlys



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值