1135 原根
Posted #忘乎所以#
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于1135 原根的主要内容,如果未能解决你的问题,请参考以下文章