原根

单求原根个数phi[phi[n]].

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 using namespace std;
 7 typedef long long ll;
 8 const int maxn = 1e5;
 9 bool flag[maxn]; //标记数组
10 ll phi[maxn]; //欧拉函数值
11 int prime[maxn]; //同时得到素数筛
12 int cnt = 0;
13 void Get_phi(int n)
14 {
15     cnt = 0;
16     memset(flag,true,sizeof(flag));
17     phi[1] = 1;
18     for(int i=2;i<=n;i++)
19     {
20         if(flag[i]) //素数
21         {
22             prime[cnt++] = i;
23             phi[i] = i-1; //素数的欧拉函数值是i-1
24         }
25         for(int j=0;j<cnt;j++)
26         {
27             if(i*prime[j]>n)
28             {
29                 break;
30             }
31             flag[i*prime[j]] = false;//素数的倍数不是素数
32             if(i%prime[j]==0) //i%mod prime = 0,那么phi(i*p) = p*phi(i)
33             {
34                 phi[i*prime[j]] = prime[j]*phi[i];
35                 break;
36             }
37             else phi[i*prime[j]] = (prime[j]-1)*phi[i];//i mod prime != 0, 那么 phi(i * prime) == phi(i) * (prime-1)
38         }
39     }
40 }
41 int main()
42 {
43     ll n;
44     Get_phi(maxn-10);
45     while(cin>>n)
46     {
47         cout<<phi[phi[n]]<<endl;
48     }
49     return 0;

求具体原根,一步一步来。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 using namespace std;
  7 typedef long long ll;
  8 const int maxn = 1e5;
  9 //欧拉函数
 10 ll euler(ll n){ //返回euler(n)
 11      ll res=n,a=n;
 12      for(ll i=2;i*i<=a;i++){
 13          if(a%i==0){
 14              res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出
 15              while(a%i==0) a/=i;
 16          }
 17      }
 18      if(a>1) res=res/a*(a-1);
 19      return res;
 20 }
 21 //线性素数筛
 22 int prime[maxn] = {0},num_prime = 0;
 23 int isNotPrime[maxn] = {1,1};
 24 void is_prime(int N)
 25 {
 26     for(int i=2;i<N;i++)
 27     {
 28         if(!isNotPrime[i])
 29         {
 30             prime[num_prime++] = i;
 31         }
 32         for(int j=0;j<num_prime&&i*prime[j]<N;j++)
 33         {
 34             isNotPrime[i*prime[j]] = 1;
 35             if(!(i%prime[j]))
 36             {
 37                 break;
 38             }
 39         }
 40     }
 41     return;
 42 }
 43 //分解质因数
 44 int curprime[maxn];
 45 int cnt = 0;
 46 void dividep(int n)
 47 {
 48     int t = sqrt(1.0*n);
 49     for(int i=0;prime[i]<=t;i++)
 50     {
 51         if(n%prime[i]==0)
 52         {
 53             curprime[cnt++] = prime[i];
 54             while(n%prime[i]==0) n /= prime[i];
 55         }
 56     }
 57     if(n>1) curprime[cnt++] = n;
 58 }
 59 int quick_pow(int a,int n,int mod)
 60 {
 61     int res = 1;
 62     while(n)
 63     {
 64         if(n&1) res = res*a%mod;
 65         n /= 2;
 66         a = a*a%mod;
 67     }
 68     return res;
 69 }
 70 int main()
 71 {
 72     ll n;
 73     is_prime(maxn-10);
 74     /*for(int i=0;i<num_prime;i++)
 75     {
 76         printf("%d ",prime[i]);
 77         if(num_prime%10==0)
 78         {
 79             printf("
");
 80         }
 81     }*/
 82     while(cin>>n)
 83     {
 84         cnt = 0;
 85         dividep(n-1);
 86         int ans = 0;
 87         for(int i=2;i<n;i++)
 88         {
 89             int flag = 0;
 90             for(int j=0;j<cnt;j++)
 91             {
 92                 int t = (n-1)/curprime[j];
 93                 if(quick_pow(i,t,n)==1)
 94                 {
 95                     flag = 1;
 96                     break;
 97                 }
 98             }
 99             if(!flag)
100             {
101                 ans++;
102             }
103         }
104         cout<<ans<<endl;
105     }
106     return 0;
107 }
原文地址:https://www.cnblogs.com/littlepear/p/7286273.html