欧拉φ函数

欧拉φ函数

 

这是我看过某同学写的之后,应为感觉自己要用所以自己摘要了一下下,
哪里写错了的地方,或哪里有意见不一致的地方还请各位路过的帮忙给改改
谢谢帮助.........


φ(n)是所有小于n的正整数里,和n互素的整数的个数。n是一个正整数。
如果n的标准素因子分解式是p1^a1*p2^a2*……*pm*am,其中众pj(j=1,2,……,m)都是素数,而且两两不等。则有
φ(n)=n(1-1/p1)(1-1/p2)……(1-1/pm)

性质
根据Fermat-Euler定理:
对任何两个互质的正整数a, m, m>=2有
a^φ(m)≡1(mod m)

当m是质数p时,此式则为
a^(p-1)≡1(mod m)

若m=m1*m2*m3*......*mk,而m1,m2,m3......mk两两互质,
则φ(m)=φ(m1)*φ(m2)*φ(m3)*φ(m4)......*φ(mk)。

a为质数
若(N % a==0 && (N/a)%a==0) 则有
φ(n) = φ(n/a)*a
若(N % a==0 && (N/a)%a!=0) 则有:
φ(n) = φ(n/a)*(a-1)

代码
不借助质数表
int euler(int n){
    int m = n, i;
    if(n % 2 == 0) m /= 2;
    while(n % 2 == 0) n /= 2;
    for(i = 3; n != 1; i += 2){
        if(n % i == 0) m -= m / i;
        while(n % i == 0) n /= i;
    }
    return m;
}
借助质数表
const int maxn = 40000;
bool pf[maxn];
int p[maxn], numOfP = 0;
void init(){
    memset(pf, 0, sizeof(pf));
    for(int i = 2; i < maxn; i++){
        if(!pf[i]){
            p[numOfP++] = i;
            for(int j = i * i; j < maxn; j += i)
                pf[j] = true;
        }
    }
}
int euler1(int n){
    int sum = 1;
    int tmp;
    for(int i = 0; i < numOfP; i++){
        if(n == 1) break;
        if(n % p[i] == 0){
            tmp = 0;
            while(n % p[i] == 0){
                n /= p[i];
                tmp++;
            }
            for(int j = 1; j < tmp; j++)
                sum *= p[i];
            sum *= p[i] - 1;
        }
    }
    if(n == 1)
        return sum;
    else
        return sum * (n - 1);
}
int euler2(int n)
{
    int i;
    for(i = 2; i <= sqrt((double)n); i++){
        if(n % i == 0 && !pf[i]){
            n /= i;
            if(n % i ==0)
                return i * euler2(n);
            else
                return (i - 1) * euler2(n);
        }
    }
    return n-1;
}


扩展欧拉函数
我们求 x1..xn,m这样的序列的个数,其中xi <= m(1<=i<=n), gcd(x1, ..,xn,m)=1;

当 n 为素数时: phi(m,n) = m^n-1
当 n 为合数时: phi(m,n) = m^n∏(1-1/p^n) 其中(p为n的素数因子)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值