欧拉函数代码实现


 欧拉函数phi(x)是指不大于正整数x的与x互质的正整数的个数。例如phi(1)=1,phi(2)=1,phi(3)=2,phi(4)=2,phi(5)=4,phi(6)=2等等。很显然,对每一个质数p,phi(p)=p-1。而对每一个质数的幂phi(p^n)=(p-1)×p^(n-1)。欧拉函数是积性函数,如果m、n互质,那么phi(m×n)=phi(m)×phi(n)。
    欧拉函数的取值需要用到算术基本定理。将n写成其质因子幂的连乘积的形式,n=p1^k1×p2^k2×…×pr^kr。那么,phi(n)=n×(1-1/p1)×…×(1-1/pr)。利用这个公式可以写出求欧拉函数的代码。当然,首先要求质数。如果问题范围是MAXSIZE,那么只需求出SIZE=sqrt(MAXSIZE)以内的质数即可。即保证任何一个数的最小质因子一定在这其中。


#include <iostream>
#include <cstdio>
using namespace std;

int oula(int n)
{
	int res = n, a = n;
	for(int i=2; i*i<=a; ++i){
		if(a%i==0){
			res = res/i*(i-1);
			while(a%i==0) a = a/i;
		}
	}
	if(a>1)res=res/a*(a-1);
	return res;
}

int main(){
	int n;
	scanf("%d",&n);
	printf("%d", oula(n));
	return 0;
}
/*
  题目内容:
  给定一个n, 求满足 2^x =1 (mod n)的最小x.
  输入描述
  输入整数n
 
  输出描述
  输出最小的x, 或者输出“不存在”
 
  输入样例
  5
 
  输出样例
  4
 
  */
  /*
  相关知识点:
  1. 若gcd(a,n)==1,一定存在一个正整数d<n使得a^phi(n) == 1 (mod n)(欧拉定理,
  phi()是欧拉函数,也经常写作 Euler() 或 phi_euler() )
  2. 如果x是满足a^x==1 (mod n)的最小正数解,则 x一定是phi(n)的约数(注意并不是
  所有的约数都满足a^x==1 (mod n) )
  证明:
  如果x是满足ax≡1 (mod n)的最小的正x, 则x<= ? (n)
  则令? (n)=tx+d, 其中余数d小于x, 则 a?(n)=a tx+d,=atx.ad
  因此满足ad=1(mod n) , 由于x是最小的,因此只好d=0
  故x整除? (n)
 
  3. 满足条件的最小正整数d记为ord_m(a),叫做a模m的阶。
  4. 若对于一个正整数a满足
  (1)gcd(a,m)==1;
  (2)ord_m(a)==φ(m)(φ(m)表示m的欧拉函数);
  则a叫做m的一个原根。
  5. 若gcd(a,m)==1且a^d == 1 mod n,则φ(m)一定是d的倍数。因此,φ(m)一定是ord_m(a)的倍数。
  6. 模m有原根的充要条件是m = 1,2,4,p^n, 2p^n,其中p是素数,n是任意正整数(只是有原根,
  并不是说gcd(a,m)==1则a一定是m的原根)。
  7. 当模m有原根时,它有φ(φ(m))个原根。
  8. 除了直接运算以外,至今还没有一个办法可以找到模特定m时的原根,但假如已知模m有一个原根,
  则可找出它其他的原根.
 
  欧拉函数的性质:
  1)n是质数,则phi(n) =n-1;
  2)m,n互质,则phi(mn) = phi(m) * phi(n)
  3)n是奇数,phi(2n)= phi(n)
  4)p是素数,a是一个正整数,那么phi(p^a)=p^a - p^(a-1)
  5)n是一个正整数,那么 Sum{ (d|n)| phi(d) } = n
 
  解题思路:
  1) 如果 n=1, 任何数模1结果都为0,所以当n=1是无解
  2) 如果 n为偶数, 因为2^x一定也是偶数 ,所以2^x % n 不可能为1,也无解。
  3) 如果 n 为奇数,则2与n互质,也即gcd(2,n)=1,由知识点(1)可知一定存在一个正整数x<n
  使得的2^x==1 (mod n),并且x一定是phi(n)的约数,进一步可得如果phi(n)是素数,则答案就是phi(n),
  否则就要去找满足条件的最小的x.
  */
   
  #include<iostream>
  #include<cstdio>
  #include<cmath>
  using namespace std;
   
  //直接求欧拉函数的值
  int euler(int n){
  int res=n;
  for(int i=2; i*i <=n; ++i){
  if( n % i == 0){
  res = res/i*(i-1);
  while(n % i == 0) n/=i;
  }
  }
  if(n>1) res = res / n * (n-1);
  return res;
  }
  //判断素数
  bool isPrime(int n){
  int i=2,Max=sqrt(n);
  for(; n%i!=0 && i<=Max; ++i);
  return i>Max;
  }
  //快速幂运算 返回 a^x % mod
  int qpow_mod(int a,int x,int mod){
  int rtn = 1,buff=a;
  while(x){
  if(x&1) rtn = rtn * buff % mod;
  buff = buff * buff % mod;
  x >>= 1;
  }
  return rtn;
  }
   
  int main(){
  int n,ans=0;
  scanf("%d",&n);
  if( n<=1 || n%2==0){
  printf("不存在");
  }else{
  int phi_n = euler(n) ;
  //如果phi_n是素数,则phi_n最小的约数就是他本身(这里不考虑1)
  if(isPrime(phi_n)) ans = phi_n;
  else{
  for(int x=2; x<=phi_n;++x) if(phi_n%x==0){
  //判断x是否满足等式2^x==1 (mod n)
  if(qpow_mod(2,x,n) == 1){
  ans=x;break;
  }
  }
  }
  printf("%d",ans);
  }
   
  return 0;
  }

*题解析来自发新大佬




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值