aoj-737-欧拉函数模板

本文介绍了欧拉函数的基本概念和性质,包括如何计算一个数的欧拉函数值,并提供了高效的算法实现。通过具体代码示例展示了如何求解单个及批量欧拉函数值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

性质:
欧拉函数用希腊字母φ表示,φ(N)表示N的欧拉函数.

对φ(N)的值,我们可以通俗地理解为小于N且与N互质的数的个数.

欧拉函数的一些性质:

1.欧拉函数是积性函数,但不是完全积性函数,即φ(mn)=φ(n)*φ(m)只在(n,m)=1时成立.

2.对于一个正整数N的素数幂分解N=P1^q1*P2^q2*…*Pn^qn.

φ(N)=N*(1-1/P1)(1-1/P2)…*(1-1/Pn).

3.除了N=2,φ(N)都是偶数.

4.设N为正整数,∑φ(d)=N (d|N).

根据性质2,我们可以在O(sqrt(n))的时间内求出一个数的欧拉函数值.

#include<cstdio>
#define ll long long
#define maxn 100000
unsigned int prime[100005],l,ans[100005],pre[100005],n;
bool flag[100005];
void Eorue()
{
     for(int i=2;i<=maxn;i++)
         {
             if(!flag[i]){
                 prime[l++] = i;
                 pre[i] = i-1;
                 ++ans[i];
             }
             for(int j=0;j<l&&prime[j]*i<=maxn;j++)
             {
                 flag[prime[j]*i] = true;
                 if(i%prime[j]==0){
                     pre[i*prime[j]] = pre[i]*prime[j];
                     break;
                 }
                 pre[i*prime[j]] = pre[i]*(prime[j]-1);
             }
         }
}
void gao()
{
     for(int i=2;i<=maxn;i++)
         for(int j=0;j<l&&prime[j]*i<=maxn;j++)
             ans[prime[j]*i] += pre[i]*2;
     for(int i=1;i<=maxn;i++)
         ans[i]+=ans[i-1];
}
int main()
{
      Eorue();
      gao();
      while(scanf("%u",&n)!=EOF)
        printf("%u\n",ans[n]);
      return 0;
}

2.0 顺便求每个数的质因子和质数信息

#include<cstdio>
#include<algorithm>
#include<iostream>
#define maxn 100001
#define LL long long
using namespace std;
// 欧拉函数3
LL eular[maxn];
int prime[maxn][15],num[maxn],flag[maxn],AM = 0;
void Eorue(){
    eular[1] = 1;
    for(int i = 2;i < maxn; i++){
        if(eular[i] == i){
            flag[AM++] = i;
            eular[i] = i - 1;
            prime[i][num[i]++] = i;
            for(int j = 2; j * i < maxn; j++){
                eular[i * j] = eular[i * j] * (i - 1) / i;
                prime[i * j][num[i * j]++] = i;
            }
        }
        eular[i] += eular[i-1];
    }
}

求单个的欧拉函数

LL get_eular(LL n){  
    LL ret=1;  
    for(int i=2;i*i<=n;i++)  
        if(n%i==0){  
            ret*=i-1;  
            n/=i;  
            while(n%i==0){  
                n/=i;  
                ret*=i;  
            }  
        }  
    if(n>1)  
        ret*=n-1;  
    return ret;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值