HDU5478 原根求解

看别人做的很简单我也不知道是怎么写出来的

自己拿到这道题的想法就是模为素数,那必然有原根r ,将a看做r^a , b看做r^b
那么只要求出幂a,b就能得到所求值a,b

自己慢慢化简就会发现可以抵消n
然后扩展欧几里得解决,一个个枚举所有模的情况。。。。

中间利用了欧拉准则可以知道 对所有奇素数而言: a^((p-1)/2) = -1(mod p) 

利用上述准则,这样就不用baby_step giant_step的办法了

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 
  5 const int N = 200010;
  6 
  7 LL P , k1,b1 , k2;
  8 bitset<N> prime;
  9 int p[N],pri[N];
 10 int k,cnt;
 11 
 12 void isprime()
 13 {
 14     prime.set();
 15     for(int i=2; i<N; i++)
 16     {
 17         if(prime[i])
 18         {
 19             p[k++] = i;
 20             for(int j=i+i; j<N; j+=i)
 21                 prime[j] = false;
 22         }
 23     }
 24 }
 25 
 26 void Divide(int n)
 27 {
 28     cnt = 0;
 29     int t = (int)sqrt(1.0*n+0.5);
 30     for(int i=0; p[i]<=t; i++)
 31     {
 32         if(n%p[i]==0)
 33         {
 34             pri[cnt++] = p[i];
 35             while(n%p[i]==0) n /= p[i];
 36         }
 37     }
 38     if(n > 1)
 39         pri[cnt++] = n;
 40 }
 41 
 42 void gcd(LL a , LL b , LL &d , LL &x , LL &y)
 43 {
 44     if(!b){d=a;x=1;y=0;}
 45     else{gcd(b,a%b,d,y,x);y-=x*(a/b);}
 46 }
 47 
 48 LL inv(LL a , LL n)
 49 {
 50     LL d,x,y;
 51     gcd(a,n,d,x,y);
 52     return d==1?(x+n)%n:-1;
 53 }
 54 
 55 LL quick_mod(LL a,LL b,LL m)
 56 {
 57     LL ans = 1;
 58     a %= m;
 59     while(b)
 60     {
 61         if(b&1)
 62         {
 63             ans = ans * a % m;
 64             b--;
 65         }
 66         b >>= 1;
 67         a = a * a % m;
 68     }
 69     return ans;
 70 }
 71 
 72 LL pow_mod(LL a , LL p , LL n)
 73 {
 74     LL ret= 1;
 75     while(p){
 76         if(p&1) ret = ret*a%n;
 77         a = a*a%n;
 78         p>>=1;
 79     }
 80     return ret;
 81 }
 82 
 83 LL mul_mod(LL a , LL b , int n)
 84 {
 85     return a*b%n;
 86 }
 87 
 88 //int log_mod(int a , int b , int n)
 89 //{
 90 //    int m , v , e=1 , i;
 91 //    m = (int)sqrt(n+0.5);
 92 //    v = inv(pow_mod(a,m,n) , n);
 93 //    map<int,int>x;
 94 //    x.clear();
 95 //    x[1] = 0;
 96 //    for(i=1 ; i<m ; i++){
 97 //        e = mul_mod(e , a , n);
 98 //        if(!x.count(e)) x[e]=i;
 99 //    }
100 //    for(i=0 ; i<m ; i++){
101 //        if(x.count(b)) return i*m+x[b];
102 //        b = mul_mod(b,v,n);
103 //    }
104 //    return -1;
105 //}
106 
107 #define pii pair<int,int>
108 pii ans[N];
109 
110 int main()
111 {
112    // freopen("a.in" , "r" , stdin);
113     int cas = 0;
114     isprime();
115     //>>k1>>b1>>k2
116     while(cin>>P>>k1>>b1>>k2)
117     {
118         printf("Case #%d:
" , ++cas);
119         int tot = 0;
120         /*P==2另外处理*/
121         if(P==1){
122             printf("%d %d
" , 0,0);
123             continue;
124         }
125         if(P==2){
126             printf("%d %d
" , 1,1);
127             continue;
128         }
129         Divide(P-1);
130 
131         for(int g=2; g<P; g++)
132         {
133             bool flag = true;
134             for(int i=0; i<cnt; i++)
135             {
136                 int t = (P - 1) / pri[i];
137                 if(quick_mod(g,t,P) == 1)
138                 {
139                     flag = false;
140                     break;
141                 }
142             }
143             if(flag)
144             {
145                 LL root = g;
146                 LL val = (P-1)/2;
147                // cout<<root<<" "<<val<<endl;
148                 LL d,x,y;
149                 gcd(b1+k1 , -1 , d , x , y);
150                 x = x*val , y = y*val;
151 
152                 x = ((x%(P-1))+(P-1))%(P-1);
153                 y = ((y%(P-1))+(P-1))%(P-1);
154                 for(int i=0 ; i<P-1 ; i++){
155 
156                     if((x*k1-y*k2)%(P-1)==0){
157                             LL a = pow_mod(root , x , P);
158                         LL b = pow_mod(root , y , P);
159                         if(a>0&&b>0) ans[tot++] = make_pair((int)a , (int)b);
160                     }
161                     x = (x+1)%(P-1);
162                     y = (y+b1+k1)%(P-1);
163                 }
164                 break;
165             }
166         }
167         sort(ans , ans+tot);
168         tot = unique(ans , ans+tot)-ans;
169         if(tot==0) puts("-1");
170         else{
171             for(int i=0 ; i<tot ; i++) printf("%d %d
" , ans[i].first , ans[i].second);
172         }
173     }
174     return 0;
175 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/4841420.html