euler欧拉函数学习入门


euler函数:对于一个数n,euler(n)的求的是在【1,n】之间与n互质的数的个数,公式为:euler(n) = n * (1 - 1/ p1) * (1 - 1/p2) * (1 - 1/p3) * ......*(1- 1/pn),其中p1,p2,.....pn是n的质因数,不重叠;

实现的算法是

typedef long long ll;
//直接求解欧拉函数
ll euler(ll x){ //返回euler(n) 
     ll ans = x;
     for(ll i = 2;i*i <= x;i ++){
         if(x%i == 0){
             res = res / i * (i-1);//先进行除法是为了防止中间数据的溢出 
             while(x % i == 0) x/=i;
         }
     }
     if(x > 1) res = res / x * (x-1);//未除尽就说明x是素数,之后进行算式
     return res;
}

//筛选法打欧拉函数表 
#define Max 1000001
ll euler[maxn];
void Init(){ 
     euler[1] = 1;
     for(ll i = 2;i < maxn;i ++)
       euler[i] = i;
     for(ll i = 2;i < maxn;i++)
        if(euler[i] == i)
           for(ll j = i;j < Max;j += i)
              euler[j] = euler[j] / i * (i-1);//先进行除法是为了防止中间数据的溢出 
}

更快的时候就是用素数表进行euler函数的运算:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 50000 + 10;
bool is_prime[maxn];
int prime[maxn];
int len = 0;
void Init()//先打个50000的素数表
{
    memset(is_prime,true,sizeof(is_prime));
    is_prime[0] = is_prime[1] = false;
    for(int i = 2; i < maxn ; i ++)
    {
        if(is_prime[i])
        {
            prime[len ++] = i;
            for(int j = i * 2; j < maxn ; j += i)
            is_prime[j] = false;
        }
            
    }
}
ll euler(ll x)
{
    ll ans = x;
    for(ll i = 0 ; prime[i] * prime[i] <= x && i < len; i ++)
    {
        if(x % prime[i])
        {
            ans = ans /prime[i] * (prime[i] - 1);
            while(x % prime[i] == 0)
                x /= prime[i];
        }
    }
    if(x > 1)
        ans = ans / x * (x - 1);
    return ans;
}
int main()//因为公式中的是x的质因数,可以先打一个素数表,之后走素数表就行了
{
    Init();
    cout << euler(2) << endl;
    return 0;
}


以上就是euler函数的实现方法,有打表和直接求;


euler的性质:

先写出两个常用定理:

1.euler定理:对于两个互质的数a,m(m>= 2),有a^(euler(m)) 1 (mod m);

2.费马小定理:当m为质数的时候a^(m - 1)   1 (mod m),因为当m为质数的时候,euler(m) = m - 1;

3.如果p是质数,那么euler(p) = p - 1;推广:p是质数,a是一个正整数,那么 euler(p^n)= p^n - p^(n - 1);

4.如果m,n是互质的两个正整数,那么euler(n*m)= euler(n)*euler(m);

5.对于一个数n,euler(n)的求的是在【1,n】之间与n互质的数的个数,公式为:euler(n) = n * (1 - 1/ p1) * (1 - 1/p2) * (1 - 1/p3) * ......*(1- 1/pn),其中p1,p2,.....pn是n的质因数,不重叠;

6.当n为奇数时,有euler(2n)= euler(n);

7.若n是一个大于2的正整数,那么euler(n)是偶数,即euler(n)%2 == 0;



euler的应用:

1.运用euler求gcd;求小于n的数 并且与n的最大公倍数gcd为i的个数 : 假设是gcd(x,n) == i ,(x < n);对于n来说,因数是i,那么说明 n/i 和 x/i互质,对于gcd(x,n) == i,如果i 一定,要 求 x的个数,就相当于求 与n/i互质的数的个数,即 x/i的个数,因为x<=n,要 求的个数就是euler(n/i)的数目; 

2.求最简真分数,即 分子小于分母 并且 分子和分母互质的分数的个数 :   就相当于   对于一个固定的分母n,求出比小且与他互质的数的个数,即euler(n);



GCD

题意:输入一个n,m,然后要求比n小的数与n的gcd大于m的个数,即gcd(x,n)>= m,其中x 属于【1,n】,求x的个数;

思路:遍历一遍,然后判断因数是不是 大于等于m,是的话就加上;

#include<iostream>
#include<cstdio>
#include<cmath>
const int maxn = 3000000 + 10;
using namespace std;
typedef long long ll;
ll euler(ll x)
{
    ll ans = x;
    for(int i = 2; i <= sqrt(x) ; i ++)
    {
        if(x % i == 0)
        {
            ans = ans / i * (i - 1);
            while(x% i == 0)
            x /= i;
        }
    }
    if(x > 1)
        ans = ans / x * (x - 1);
    return a
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值