欧拉函数相关的题目

POJ 1284
 
求原根个数:
  即求 euler(euler(p)) = euler(p-1) 其中p为奇素数
  又有 euler(x) = x*(1-1/p1)*...*(1-1/pk)  其中pk为x的质因数
#include <cstdio>
#include <cstring>

int all, p, ans, num[100000];
bool pd[100000];

int main()
{
    pd[1] = 1;
    for(int i = 1; i < 100000; i++)
        if(!pd[i])
        {
            num[all++] = i;
            for(int j = i+i; j < 100000; j += i)
                pd[j] = 1;
        }
    while(scanf("%d", &p) != EOF)
    {
        ans = --p;
        for(int i = 0; i < all && num[i] <= p; i ++)
            if(p%num[i] == 0)
                ans = ans/num[i]*(num[i]-1);
        printf("%d\n", ans);
    }
    return 0;
}
View Code
 
 
POJ 2407
求与n互质的个数:
  即求euler(n)
#include <cstdio>
#include <cstring>

int all, num[100000], ans, n;
bool pd[100000];

int main()
{
    pd[1] = 1;
    for(int i = 1; i <= 100000; i++)
        if(!pd[i])
        {
            num[all++] = i;
            for(int j = i+i; j <= 100000; j += i)
                pd[j] = 1;
        }
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;
        ans = n;
        for(int i = 0; i < all && num[i] <= n; i ++)
            if(n%num[i] == 0)
            {
                ans = ans/num[i]*(num[i]-1);
                while(n%num[i] == 0)
                    n /= num[i];
            }
        if(n != 1)
            ans = ans/n*(n-1);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

POJ 2478

求解前n项欧拉函数之和

看到网上一个比较漂亮的求解欧拉函数的方法。

整个求法其实类似筛法求素数。

对于任何数 x = 2^k * p 其中p为奇数,以下用phi即那个希腊字符表示欧拉函数

故 对于k>0 phi[x] = 2^k * ( 1 - 1/2) * phi[p] = 2^(k-1) * phi[p] = 2^(k-1) * p * (1-1/p1) * ... * (1- 1/pn) = x/2 * (1-1/p1) * ... * (1- 1/pn) 其中p1 .. pn 为p的质因子。 故每次筛法求出素数时可以向上进行求解欧拉函数。

    对于k=0 phi[x] = x * (1-1/p1) * ... * (1- 1/pn)

故有此算法

可以大致看出 复杂度不差于O(nlgn) 

#include <cstdio>
#include <cstring>
#define MAXN 1000005
int phi[MAXN], n;
long long sum[MAXN];

void get_phi()
{
    phi[1] = 0;
    for(int i = 2; i < MAXN; i++)
        if(i&1)
            phi[i] = i;
        else
            phi[i] = i/2;
    for(int i = 2; i < MAXN; i++)
        if(phi[i] == i) // i为素数
            for(int j = i; j < MAXN; j += i)
                phi[j] = phi[j]/i*(i-1);
}

int main()
{
    get_phi();
    for(int i = 1; i < MAXN; i ++)
        sum[i] = sum[i-1]+phi[i];
    while(scanf("%d", &n) != EOF && n)
        printf("%lld\n", sum[n]);
    return 0;
}
View Code

 

posted @ 2014-11-11 17:37  Estimator  阅读(737)  评论(0编辑  收藏  举报