zoukankan      html  css  js  c++  java
  • 欧拉函数模板

    一、单个欧拉函数计算

    可评测链接:http://codevs.cn/problem/4939/

    单个欧拉函数计算公式:φ(n)=n*(1-1/p1)*(1-1/p2)*……*(1-1/pn)

    Step 1:

    一边分解质因数一边算,时间复杂度O(n)

    #include<cstdio>
    using namespace std;
    long long n,ans;
    int main()
    {
        while(1)
        {
            scanf("%lld",&n);
            if(!n) break;
            ans=n;
            for(long long i=2;i<=n;i++)
             if(n%i==0)
             {
                 while(n%i==0) n/=i;
                 ans=ans/i*(i-1);
             }
            printf("%lld
    ",ans);
        }
    }

    Step 2 :

    性质:合数至少有一个不大于不大于根号n的素因子

    所以循环只需循环到根号n即可 时间复杂度 O(根号n)

    #include<cstdio>
    using namespace std;
    long long n,ans;
    int main()
    {
        while(1)
        {
            scanf("%lld",&n);
            if(!n) break;
            ans=n;
            for(long long i=2;i*i<=n;i++)
             if(n%i==0)
             {
                 while(n%i==0) n/=i;
                 ans=ans/i*(i-1);
             }
            if(n>1) ans=ans/n*(n-1);
            printf("%lld
    ",ans);
        }
    }

    Step 3:

    素数除了2之外都是奇数,

    所以单独处理2,然后之枚举根号n以内的奇数

    时间复杂度 O[(根号n)/2]

    #include<cstdio>
    using namespace std;
    int main()
    {
        long long n,ans;
        while(1)
        {
            scanf("%lld",&n);
            if(!n) return 0;
            ans=n;
            if(n%2==0)
            {
                while(n%2==0) n/=2;
                ans=ans/2;
            }
            for(long long i=3;i*i<=n;i+=2)
               if(n%i==0)
                {
                    while(n%i==0) n/=i;
                    ans=ans/i*(i-1);
                }
            if(n>1) ans=ans/n*(n-1);
            printf("%lld
    ",ans);
        }
    }

    二、欧拉筛

    欧拉筛可以快速求[1,n]内所有数的欧拉函数,所以在涉及欧拉函数求和时会使用

     利用性质:

    如果i%p==0,那么φ(i*p)=φ(i)*p

    如果i%p!=0,那么 φ(i*p)=φ(i)*(p-1)   其中p为质数

    代码为求2——n的欧拉函数之和

    评测链接:http://poj.org/problem?id=2478

    时间复杂度:O(n)

    #include<cstdio>
    #define N 1000001 
    using namespace std;
    bool check[N];
    int prime[N],cnt,phi[N],a;
    long long sum[N];
    void euler()
    {
        phi[1]=1;
        for(int i=2;i<=N;i++)
        {
            if(!check[i])
            {
                prime[++cnt]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=cnt;j++)
            {
                if(i*prime[j]>N) break;
                check[i*prime[j]]=true;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
    }
    int main()
    {
        euler();
        for(int i=1;i<=N;i++) sum[i]+=sum[i-1]+1ll*phi[i];
        while(1)
        {
            scanf("%d",&a);
            if(!a) return 0;
            printf("%lld
    ",sum[a]-1);
        }
    }

    三、埃氏筛法

    埃氏筛法可以O(1)查询i是否与n互质,在涉及 查询与n互质的数是什么 时 会使用

    时间复杂度:O(nlog²n)

    下方代码为求与n互质的第k个数

    评测链接:http://poj.org/problem?id=2773

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    bool check[1000001];
    int euler(int n)//埃氏筛法模板 
    {
        int m=int(sqrt(n+0.5));
        int ans=n,k=n;
        memset(check,0,sizeof(check));
        for(int i=2;i<=m;i++)
         if(n%i==0)
         {
             ans=ans/i*(i-1);
             for(int j=1;i*j<=k;j++)
              check[i*j]=true;
             while(n%i==0) n/=i;
         }
        if(n>1)
        {
            ans=ans/n*(n-1);
            for(int j=1;n*j<=k;j++) 
             check[n*j]=true;
        }
        return ans;
    }
    int main()
    {
        int m,k,ans,cnt,t,i;
        while(scanf("%d%d",&m,&k)!=EOF)
        {
            ans=euler(m);
            cnt=0;
            if(k%ans==0) t=k/ans-1;
            else t=k/ans;
            k=k-ans*t;
            for(i=1;i<=m;i++)
            {
                if(!check[i]) cnt++;
                if(cnt==k) break;
            }
            printf("%d
    ",i+m*t);
        }
    }
  • 相关阅读:
    JNI编程基础
    C语言指针学习
    C语言字符串以及二维数组指针
    CPP数据类型本质以及变量本质分析
    junit在idea中的使用(2)--实践篇
    idea创建maven项目
    SourceTree的基本使用---团队开发/参与开源
    SourceTree的基本使用---基本介绍/本地开发
    流量分析系统---启动流程
    流量分析系统---redis
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6598367.html
Copyright © 2011-2022 走看看