欧拉函数 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;
}
输入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);
}