3520. 【NOIP2013模擬11.7B組】原根
阿新 • • 發佈:2018-12-16
Description
Input
有且只有一個正整數m。
Output
以遞增序依次輸出模m的所有原根,每行輸出一個原根。 如果不存在模m的原根,輸出-1。
Sample Input
7
Sample Output
3
5
Data Constraint
50%的資料,m≤ 200。 100%的資料,m ≤ 10000。
Hint
樣例解釋:
Solution
題目是簡單的,完全按照題目描述的方式模擬就可以了。 主要是考察選手會不會對數學題頭昏,以及gcd函式怎麼寫
意思就是暴力。時間複雜度O(m^2);
有人(某大佬)認為這樣的時間複雜度過不了極限資料(其實我也是這麼認為,但是不知為何偏偏就過了),於是想出了一種O(m*根號m*long m)的時間複雜度,這裡來講一下:首先我們知道如果1到fai(m)中可能有很多個
Code1
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> using namespace std; int n,p,x,s,ans=0; bool bz; int fai(int x){ int q=x; for(int i=2;i<=x;i++){ if(x%i==0){ q=q*(i-1)/i; while(x%i==0) x/=i; } } if(x>1) q=q*(x-1)/x; return q; } int gcd(int x,int y){ if(x%y==0) return y; else return gcd(y,x%y); } int main(){ freopen("math.in","r",stdin); freopen("math.out","w",stdout); scanf("%d",&n); if(n==1){printf("1");return 0;} p=fai(n); for(int i=1;i<=n-1;i++){ if(gcd(i,n)!=1) continue; x=s=i;bz=1; for(int j=1;j<=p-1;j++){ if(s==1){bz=0;break;} s=(s*x)%n; } if(bz){ans++;printf("%d\n",i);} } if(!ans) printf("-1\n"); return 0; }
Code2
#include<cstdio> using namespace std; int zh[10010],ys[10010]; int m,phi=0,tot=0,cnt=0; bool bz[10010],check,all=0; int ksm(int x,int y) { int s=1; while (y) { if (y & 1) s=s*x%m; x=x*x%m; y>>=1; } return s; } int main() { freopen("math.in","r",stdin); freopen("math.out","w",stdout); scanf("%d",&m); if (m==0) return 0&puts("-1"); else if (m==1 || m==2) return 0&puts("1"); for (int i=2;i<=m;i++) if (!bz[i]) { zh[++tot]=i; if (m%i) continue; for (int j=1;j<=m/i;j++) bz[i*j]=true; } for (int i=1;i<=m;i++) if (!bz[i]) phi++; for (int i=1,x=phi;i<=tot && x>1;i++) if (x%zh[i]==0) { ys[++cnt]=zh[i]; while (x%zh[i]==0) x/=zh[i]; } for (int i=2;i<m;i++) if (!bz[i]) { check=1; for (int j=1;j<=cnt;j++) if (ksm(i,phi/ys[j])==1) {check=0; break;} if (check) all=1,printf("%d\n",i); } if (!all) puts("-1"); return 0; }