c++实现求解欧拉函数和本原根

计算本原根

这里我不详细解释欧拉函数和本原根。
首先我们先了解求一个数的本原根的过程,以25为例:

25的本原根

1.在计算25的所有本原根时,首先我们要得到25的欧拉函数值可以知道25=5^2,其欧拉函数值=25-5=20
且这20个数为1,2,3,4,6,7,8,9,11,12,13,14,16,17,18,19,21,22,23,24。
2.接着遍历这些数依次求解这些数的1-20次方对25取余,并且这20个数不重复,且均在这些数里,编程里体现为对求得的20个数排序再比较。
3.由于高次幂会溢出,参考了大数计算优化的快速幂取余算法解决了这个问题。

求25的本原根的源代码

#include<iostream>
using namespace std;

void bubbleSort(int arr[], int n);//冒泡排序
int power(long int x, long int y, long int n);//快速幂取余实现(x^y%n)

int main()
{
	int i,j,k,flag[20];
	int n=25,sum=20;
	int s[20]={1,2,3,4,6,7,8,9,11,12,13,14,16,17,18,19,21,22,23,24}; 
	cout<<"25的所有本原根为:";
	for(i=0;i<sum;i++)
	{
		k=0;
		for(j=1;j<sum+1;j++)
		{
			//这里要利用快速幂取余,否则数值太大会溢出
			flag[j-1]=power(s[i],j,n);
		}
		bubbleSort(flag,sum);
		
		for(j=0;j<sum;j++)
		{
			if(flag[j]!=s[j])
				k=1;
		}
		if(k==0)
			cout<<s[i]<<" ";
	}
	cout<<endl<<endl;
	return 0;
}

//冒泡排序
void bubbleSort(int arr[], int n)
{
	for(int i = 0;i < n;i++)
	{  
		for(int j = 0;j < n-i-1;j++)
		{  
            if(arr[j] > arr[j+1])
			{  
                int t = arr[j];  
                arr[j] = arr[j+1];  
                arr[j+1] = t;  
            }  
        }  
    }       
}
//快速幂取余实现(x^y%n)
int power(long int x, long int y, long int n)
{
	long int t = 1;
	while (y > 0)
	{
		if (y % 2 == 1)
		{
			y -= 1;
			t = t*x%n;
		} else {
			y /= 2;
			x = x*x%n;
		}
	}
	return t%n;
}

结果

在这里插入图片描述

扩展为求输入数字的本原根

#include<iostream>
using namespace std;

//判断两个数是否互素
int IsPrime(int a, int b)
{
	int temp;
	while(b!=0)
	{
		temp = b;
		b = a % b;
		a = temp;
	}
	
	if(a==1)
		return 1;
	else
		return 0;
}

//得到欧拉函数的值和取值集合
void Euler(int n,int *s,int &sum)
{
	int i,flag;
	for(i=1;i<n;i++)
	{
		flag=IsPrime(i,n);
		if(flag==1)
		{
			s[sum]=i;
			sum++;
		}
	}
}

//冒泡排序
void bubbleSort(int arr[], int n)
{
	for(int i = 0;i < n;i++)
	{  
		for(int j = 0;j < n-i-1;j++)
		{  
            if(arr[j] > arr[j+1])
			{  
                int t = arr[j];  
                arr[j] = arr[j+1];  
                arr[j+1] = t;  
            }  
        }  
    }       
}

//快速幂取余实现(x^y%n)
int power(long int x, long int y, long int n)
{
	long int t = 1;
	while (y > 0)
	{
		if (y % 2 == 1)
		{
			y -= 1;
			t = t*x%n;
		} else {
			y /= 2;
			x = x*x%n;
		}
	}
	return t%n;
}

//根据互素集合利用遍历的方法求本原根
void root(int n,int sum,int s[])
{
	int i,j;
	int flag[100],k;
	for(i=0;i<sum;i++)
	{
		k=0;
		for(j=1;j<sum+1;j++)
		{
			//这里要利用快速幂取余,否则数值太大会溢出
			flag[j-1]=power(s[i],j,n);
		}
		bubbleSort(flag,sum);
		
		for(j=0;j<sum;j++)
		{
			if(flag[j]!=s[j])
				k=1;
		}
		if(k==0)
			cout<<s[i]<<" ";
	}
}

int main()
{
	int n,sum=0;
	int s[100];  //用来存储比n小且与n互素的正整数
	cout<<"请输入你想要求本原根的数:";
	cin>>n;
	Euler(n,s,sum);
	cout<<endl;
	cout<<n<<"的所有本原根为:";
	root(n,sum,s);
	cout<<endl<<endl;
	return 0;
}

结果:

在这里插入图片描述

发布了7 篇原创文章 · 获赞 4 · 访问量 1184

猜你喜欢

转载自blog.csdn.net/weixin_40520963/article/details/86685657