1135 原根

1135 原根

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
收藏
关注
设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。(其中φ(m)表示m的欧拉函数)
给出1个质数P,找出P最小的原根。
Input
输入1个质数P(3 <= P <= 10^9)
Output
输出P最小的原根。
Input示例
3
Output示例
2
这竟然是基础题,(让我死会儿),第一次看题目,一脸懵逼,完全不懂题目讲什么,
然后百度一下词条,发现有规律可寻,于是暴力了一下,超时瞬间崩溃,不知道要,
怎么做了,无奈看了一下大佬们的题解,原来是可以优化的,只是也挺麻烦.

阶:gcd(a,m)=1,使得这里写图片描述成立的最小的 r,称为 a 对 模m 的 阶。

φ(m):在[1,m)的区间内与m互质的数的个数。

求模素数p的原根a的方法:

因为p为素数,所以φ(p)=p-1, 这题就是要找最小的a使得 a^(p-1)%p = 1 成立(根据费马小定理,该式一定成立),

先求p-1所有不同的 质因子 p1,p2…pm,

对任何整数 a ∈[1,p-1], 检验 a 是否为 p 的原根,

检验方法:a^((p-1)/p1),a^((p-1)/p2),...a^((p-1)/pm) 中是否存在一个 模p 等于 1 ,

存在的话 a 就不是 模p 的一个原根(即p-1就不是a对模p的阶),否则a就为原根。

上面是我看到的大佬的解释,个人觉得比较好,就拿过来了.

 

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 #define N 1000010
 4 #define mem(a)  memset(a,0,sizeof(a))
 5 #define bug cout<<"****"<<endl
 6 using namespace std ;
 7 int pri[N],p[N],prime[N],xn=0,cnt=0;
 8 
 9 void isprime(){  //求出素数
10   mem(p);mem(prime);
11   for(int i=2;i<N;i++){
12     if(!prime[i])
13       p[xn++]=i;
14     for(int j=2;j*i<N;j++){
15       prime[i*j]=1;
16     }
17   }
18 }
19 
20 void divide(int n){//将P-1分解质因数
21   int t=(int)sqrt(n*1.0);mem(pri);
22   for(int i=0;p[i]<=t;i++){
23     if(n%p[i]==0){
24       pri[cnt++]=p[i];
25       while(n%p[i]==0)
26         n/=p[i];
27     }
28   }
29   if(n>1)
30     pri[cnt++]=n;
31 }
32 
33 ll pow_mod(ll a,ll b,ll mod){//快速幂
34   ll ans=1;
35   a%=mod;
36   while(b){
37     if(b&1)
38       ans=(ans*a)%mod;
39     b>>=1;
40     a=(a*a)%mod;
41   }
42   return ans;
43 }
44 int main(){
45   int n;
46   isprime();//获得质数
47   scanf("%d",&n);
48   divide(n-1);//将n-1分解质因数
49   for(int i=2;i<n;i++){//从2开始遍历
50     bool prime=true;
51     for(int j=0;j<cnt;j++){
52       int t=(n-1)/pri[j];
53       if(pow_mod(i,t,n)==1){
54         prime=false;
55         break;
56       }
57     }
58     if(prime){
59       printf("%d\n",i);
60       break;
61     }
62   }
63   return 0;
64 }

 

 

 

转载于:https://www.cnblogs.com/zllwxm123/p/7382581.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值