题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1135
题意:中文题诶~
思路:设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。(其中φ(m)表示m的欧拉函数)给出1个质数P,找出P最小的原根。
我们先了解一下阶的概念:满足 a^r Ξ (1 mod m) ---1 的最小 r 即为 a%m的阶,我们可以直接从小到大枚举a, 然后将 r= φ(m) 带入进去,
判断如果满足 1式(即 a^x%m=1当且仅当 x=r 时成立)的话即为我们所求的答案。又因为输入的 m为质数,所以 r= φ(m)=m-1.
判断对于当前 a,x=m-1 是否是 a^x%m=1---2 成立的唯一解我们不可能直接从正面枚举每个x,因为我们并不知道是否存在一个数 n, x>n时2式一定不成立,也就是我们不能确定枚举 x 的范围,那么枚举 x 也就无从谈起咯。不过还有有这样一个定理 对 (m-1) 只因分解成 m1, m2, m3....mk,若存在 x=(m-1)/mi 使得式2成立,那么
当前 a 不是 a mod m 的原根。所以我们就可以从反面枚举 x 啦,若当前 a 使得 x=(m-1)/mi (1<=i<=k)对于式2都不满足, 那么当前 a 即为所求解啦~
代码:
1 #include <bits/stdc++.h> 2 #define ll long long 3 #define MAXN 100 4 using namespace std; 5 6 ll prime[MAXN]; 7 int cnt=0; 8 9 void make_prime(ll x){ 10 for(int i=2; i*i<=x; i++){ 11 if(x%i==0){ 12 prime[cnt++]=i; 13 while(x%i==0){ 14 x/=i; 15 } 16 } 17 } 18 if(x>1){ 19 prime[cnt++]=x; 20 } 21 } 22 23 ll get_pow(ll x, int n, int mod){ 24 ll ans=1; 25 while(n){ 26 if(n&1){ 27 ans=ans*x%mod; 28 } 29 x=x*x%mod; 30 n>>=1; 31 } 32 if(ans<0){ 33 ans+=mod; 34 } 35 return ans; 36 } 37 38 int main(void){ 39 ll m; 40 scanf("%lld", &m); 41 make_prime(m-1); 42 for(int i=2; i<m; i++){ 43 int flag=1; 44 for(int j=0; j<cnt; j++){ 45 int x=(m-1)/prime[j]; 46 if(get_pow(i, x, m)==1){ 47 flag=0; 48 break; 49 } 50 } 51 if(flag){ 52 printf("%d\n", i); 53 return 0; 54 } 55 } 56 return 0; 57 }
时间: 2024-10-10 21:18:51