求欧拉函数

欧拉函数 phi(n)

性质:

1.若a为质数,phi[a]=a-1;
2.若a为质数,b mod a=0,phi[a*b]=phi[b]*a
3.若a,b互质,phi[a*b]=phi[a]*phi[b](当a为质数时,if b mod a!=0 ,phi[a*b]=phi[a]*phi[b])

n   == 1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30

phi(n) 1   1   2   2   4   2   6   4   6    4    10    4   12     6     8     8   16     6    18    8    12   10   22    8    20   12   18   12   28    8    

求欧拉函数普通版

//欧拉函数
int phi(int x){
    int ans = x;
    for(int i = 2; i*i <= 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 ans;
}

HDU 2824

输入a+b,求uola(a)+oula(a+1)+oula(a+2)+......+oula(b)

input:

3  100

output:

3042

#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;

typedef long long LL;

const int MAXN = 3000000 + 5;

bool vis[MAXN];
int prime[MAXN], tot;
int euler[MAXN];

void toInit()
{
    tot = 0;
    for (int i = 2;i < MAXN;i++)
    {
        if (!vis[i])
            prime[tot++] = i;
        for (int j = 0;j < tot&&prime[j] * i < MAXN;j++)
        {
            vis[prime[j] * i] = 1;
            if (i%prime[j] == 0)
                break;
        }
    }
}

void getEuler()
{
    for (int i = 1;i < MAXN;i++)
        euler[i] = i;
    for (int i = 0;i < tot;i++)
        for (int j = prime[i];j < MAXN;j += prime[i])
            euler[j] /= prime[i], euler[j] *= (prime[i] - 1);
}

int main()
{
    toInit();
    getEuler();
    for (int a, b;scanf("%d%d", &a, &b) == 2;)
    {
        LL ans = 0;
        for (int i = a;i <= b;i++)
            ans += euler[i];
        printf("%I64d\n", ans);
    }
    return 0;
}

 

 

求一个大数的欧拉函数(速度好像不是很快)

input:

5

output:

4

n<=10^18

下面这个代码,一组输入正确,不知道为什么,改成多组输入就错了,莫名其妙。

以下代码转自:https://blog.csdn.net/qq_35914587/article/details/78171711

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#define ll long long
using namespace std;
ll prime[99999],cnt;
ll gcd(ll a,ll b)
{
    if(!b) return a;
    return gcd(b,a%b);
}
ll mul(ll x,ll y,ll mod)//快速加
{
    ll ans=0;
    while(y)
    {
        if(y%(1ll*2)) ans=(ans+x%mod)%mod;
        y/=(1ll*2);
        x=(x%mod+x%mod)%mod;
    }
    return ans;
}
ll fast_pow(ll x,ll y,ll m)//快速幂
{
    ll ans=1;
    x%=m;
    while(y)
    {
        if(y%2)
            ans=mul(ans, x, m);
        y/=2;
        x=mul(x, x, m);
    }
    return ans;
}
bool MR(ll n)
{
    if(n == 2) return 1;
    if(n < 2 || !(n & 1)) return 0;
    ll m=n-1;
    ll k=0;
    while((k&1)==0)
    {
        k++;
        m/=2;
    }
    for(int i=0; i<12; i++)
    {
        ll a=rand()%(n - 1)+1;
        ll x=fast_pow(a, m, n);
        ll y=0;
        for(int j=0; j<k; j++)
        {
            y=mul(x,x,n);
            if(y==1&&x!=1&&x!=n-1) return 0;
            x = y;
        }
        if(y!=1) return 0;
    }
    return 1;
}
ll rho(ll n,ll c)//找因子
{
    ll i=1,k=2;
    ll x=rand()%(n-1)+1;
    ll y=x;
    while(1)
    {
        i++;
        x=(mul(x,x,n)+c)%n;
        ll d=gcd(((y-x)+n)%n,n)%n;
        if(d>1&&d<n) return d;
        if(y==x) return n;
        if(i==k)//一个优化,我也不知道为啥
        {
            y=x;
            k<<=1;
        }
    }
}
void find(ll n,ll c)//分解的递归过程
{
    if(n==1) return;
    if(MR(n))
    {
        prime[++cnt]=n;
        return;
    }
    ll p=n;
    ll k=c;
    while(p>=n) p=rho(n,c--);
    find(n/p,c);
    find(p,c);
}
int main()
{
    ll n;
    scanf("%lld",&n);
    find(n,120);
    sort(prime+1,prime+cnt+1);
    ll t=unique(prime+1,prime+cnt+1)-prime-1;//去重函数,不要忘了去了重复的质数啊

    /* for(int i=1;i<=t;i++)
     printf("%lld ",prime[i]);*/
    double ans=n;
    for(int i=1; i<=t; i++)
        ans*=(1.0-(1.0/(double)prime[i]));
    printf("%lld",(ll) ans);
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值