51nod 1135 Primitive Root Solution Report (Euler Function,)

Reference resources: https://blog.csdn.net/zhouyuheng2003/article/details/80163139#comments

Title:

Let m be a positive integer and a be an integer. If the order of a module M equals phi (m), then a is called a primitive root of a module M. (where_(m) denotes the Euler function of m)

Give a prime number P and find the primitive root of the minimum P.

Input

Enter a prime number P(3 <= P <= 10 ^ 9)

Output

The original root with the smallest output P.

Input example

3

Output example

2

 

Relevant knowledge:

Let's first understand the meaning of the order of a module m: the n-th-power module M remainder 1 of a, in which the order of a module M is the order that satisfies the minimum condition.

If n==phi(m), then a is a primitive root of M.

And:

(The inverse element of Euler's theorem is universal)

Euler's Theorem: For any two positive integers a, m (m >=2) has

Namely:

  

Therefore:

            It is the inverse element of a under module m. _ The number of positive integers less than m and mutually prime with M

For m, the minimum primitive root a is obtained.

a ->  2...
    if a^phi(m)!=1MOd m 
        continue;
    i -> 1..(phi(m)-1)
       If a^i==1 mod m
            Explain that this a does not conform
    If they all agree, then this a is the answer.

Code: (This violence will be timed out)

// #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

 
using namespace std;
#define ll long long 


int phi(int n)
{
	int m=sqrt(n+0.5);
	int ans=n;
	for(int i=2;i<=m;i++) if(n%i==0)
	{
		ans=ans/i*(i-1);
		while(n%i==0) n/=i;
	}
	if(n>1)
	{
		ans=ans/n*(n-1);
	}
	return ans;
		
}


ll pow(ll a,ll b,ll mod)
{
	ll base=a;
	ll sum=1;
	while(b)
	{
		if(b&1)
			sum=(sum*base)%mod;
		b>>=1;
		base=(base*base)%mod;
	}
	return sum;
	
}

int G(int n)
{
	int Phi=phi(n);
	int g;
	for(g=2;;g++)
	{
		if(pow(g,Phi,n)!=1) continue;
		int flag=0;
		for(int i=1;i<Phi;i++)
		{
			if(pow(g,i,n)==1) 
			{
				flag=1;
				break;
			}
			
		}
		if(!flag) break;	
		

	}
	return g;
}

int main()
{
	int p;
	while(~scanf("%d",&p))
	{
		int g=G(p);
		printf("%d\n",g);
	}


	return 0;
}

A little improvement:

It's the factor that changes i from 1 to phi(m)-1 to phi(m) in ergodic g^i

// #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

 
using namespace std;
#define ll long long 


int phi(int n)
{
	int m=sqrt(n+0.5);
	int ans=n;
	for(int i=2;i<=m;i++) if(n%i==0)
	{
		ans=ans/i*(i-1);
		while(n%i==0) n/=i;
	}
	if(n>1)
	{
		ans=ans/n*(n-1);
	}
	return ans;
		
}


ll pow(ll a,ll b,ll mod)
{
	ll base=a;
	ll sum=1;
	while(b)
	{
		if(b&1)
			sum=(sum*base)%mod;
		b>>=1;
		base=(base*base)%mod;
	}
	return sum;
	
}
int q[100100];

int G(int n)
{
	int Phi=phi(n);
	int g;
	int cnt=0;
	int temp=(int)(sqrt(Phi+0.5));
	for(int i=1;i<=temp;i++)
	{
		if(Phi%i==0)
		{
			q[cnt++]=i;
			if(i!=1)q[cnt++]=Phi/i;
		}
	}
	for(g=2;;g++)
	{
		if(pow(g,Phi,n)!=1) continue;
		int flag=0;
		for(int i=0;i<cnt;i++)
		{
			if(pow(g,q[i],n)==1) 
			{
				flag=1;
				break;
			}
			
		}
		if(!flag) break;	
		

	}
	return g;
}

int main()
{
	int p;
	while(~scanf("%d",&p))
	{
		int g=G(p);
		printf("%d\n",g);
	}


	return 0;
}

Implementation code: --"The code is really hard to understand. (Fortunately, now you can see the following.)

The following code only changes the factor of i-traversal phi(m) traversing g^i to the factor of phi(m) traversal only in the section [sqrt (phi(m)~phi (m)-1].

i don't know why i changed range i to [1, sqrt (phi(m)]. The factor of phi(m) is WA.

/* 51nod 1135 Primitive root */


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
const int mod=1e9+7;
ll prime[100];
int cnt=0;

void make_prime(ll x)
{
    for(int i=2;i*i<=x;i++) if(x%i==0)
    {
        prime[cnt++]=i;
        while(x%i==0) x/=i;
    }
    if(x>1)
        prime[cnt++]=x;
}
ll quick_mod(ll base, int n, int mod) //Fast power remainder
{
    ll ans=1;
    while(n)
    {
        if(n&1) ans=ans*base%mod;
        base=base*base%mod;
        n>>=1;
    }
    if(ans<0)
        ans+=mod;
    return ans;
}
int main()
{
    int m;
    scanf("%lld", &m);
    make_prime(m-1);
    for(int i=2;i<m;i++)
    {
        int flag=1;
        for(int j=0;j<cnt;j++)
        {
            int x=(m-1)/prime[j];
            if(quick_mod(i,x,m)==1)
            {
                flag=0;
                break;
            }
        }
        if(flag)
        {
            printf("%d\n",i);
            break;
        }
    }
    return 0;
}

 

 

 

Keywords: less

Added by dvd420 on Fri, 02 Aug 2019 13:14:17 +0300