原根存在的充要条件
n = 1,2,4,p^r (p为奇素数,r为任意正整数)
原根的性质
若n存在原根,则原根个数为φ(φ(n))
若g是n的一个原根,则g^d是n的原根的充要条件为gcd(d,φ(n)) = 1
一个数的全体原根乘积模n余1
一个数的全体原根和模n余μ(n-1)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; bool isprime[1000001]; LL prime[100001]; LL primesize = 0,n,ans[10001],p; LL res[1000005]; LL gcd(LL a,LL b){ if (b == 0) return a; return gcd(b,a % b); } LL Fast_Mod(LL a,LL b,LL p){ LL res = 1,base = a; while (b){ if (b&1) res = (res*base) % p; base = (base*base) % p; b = b >> 1; } return res; } void initPrime(){ memset(isprime,1,sizeof(isprime)); isprime[1] = false; LL ListSize = 1000000; for (LL i=2;i<= ListSize ; i++){ if (isprime[i]) { primesize ++; prime[primesize] = i; } for (int j=1;j<=primesize && i*prime[j] <= ListSize; j++){ isprime[i*prime[j]] = false; if (i % prime[j] == 0) break; } } } LL phi(LL n){ LL i,rea=n; for(i=2;i*i<=n;i++) { if(n%i==0) { rea=rea-rea/i; while(n%i==0) n/=i; } } if(n>1) rea=rea-rea/n; return rea; } bool exist(LL n){ if (n % 2 == 0) n /= 2; if (isprime[n]) return 1; for (int i=3;i*i<=n;i+=2){ if (n % i == 0){ while (n % i == 0) n /= i; return (n == 1); } } return 0; } int main() { // freopen("test.in","r",stdin); initPrime(); while(scanf("%lld",&p)!=-1) { int cnt=0; if (p == 2) { cout << 1 << endl; continue; } if (p == 4){ cout << 3 << endl; continue; } if (!exist(p)){ cout << -1 << endl; continue; } n = phi(p); for(int i=1;i<=primesize&&prime[i]*prime[i]<=n;i++) { if(n%prime[i]==0) { n/=prime[i]; cnt ++; ans[cnt]=prime[i]; while(n%prime[i]==0) { n/=prime[i]; } } } if(n!=1){ cnt ++; ans[cnt]=n; } n = phi(p); LL g; for (int i=2;i<p;i++){ if (gcd(i,p) == 1){ int ok = 1; for (int j=1;j<=cnt;j++){ if (Fast_Mod(i,n/ans[j],p) == 1){ ok = 0; break; } } if (ok){ g = i; break; } } } LL total = 0; for (int i=1;i<=n;i++){ if (gcd(i,n) == 1){ total ++; res[total] = Fast_Mod(g,i,p); } } sort(res+1,res+total+1); for (int i=1;i<=total-1;i++){ cout << res[i] << " "; } cout << res[total] << endl; } return 0; }
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long LL; bool isprime[1000001]; LL prime[100001]; LL primesize = 0,n,ans[10001],p; LL gcd(LL a,LL b){ if (b == 0) return a; return gcd(b,a % b); } LL Fast_Mod(LL a,LL b,LL p){ LL res = 1,base = a; while (b){ if (b&1) res = (res*base) % p; base = (base*base) % p; b = b >> 1; } return res; } void initPrime(){ memset(isprime,1,sizeof(isprime)); isprime[1] = false; LL ListSize = 1000000; for (LL i=2;i<= ListSize ; i++){ if (isprime[i]) { primesize ++; prime[primesize] = i; } for (int j=1;j<=primesize && i*prime[j] <= ListSize; j++){ isprime[i*prime[j]] = false; if (i % prime[j] == 0) break; } } } LL phi(LL n){ LL i,rea=n; for(i=2;i*i<=n;i++) { if(n%i==0) { rea=rea-rea/i; while(n%i==0) n/=i; } } if(n>1) rea=rea-rea/n; return rea; } int main() { // freopen("test.in","r",stdin); initPrime(); while(scanf("%lld",&p)!=-1) { int cnt=0; n = phi(p); for(int i=1;i<=primesize&&prime[i]*prime[i]<=n;i++) { if(n%prime[i]==0) { n/=prime[i]; cnt ++; ans[cnt]=prime[i]; while(n%prime[i]==0) { n/=prime[i]; } } } if(n!=1){ cnt ++; ans[cnt]=n; } bool find = 0; n = phi(p); for (int i=2;i<p;i++){ if (gcd(i,p) == 1){ int ok = 1; for (int j=1;j<=cnt;j++){ if (Fast_Mod(i,n/ans[j],p) == 1){ ok = 0; break; } } if (ok){ find = 1; break; } } } if (find){ cout << phi(phi(p)) << endl; } else { cout << 0 << endl; } } return 0; }