看别人做的很简单我也不知道是怎么写出来的
自己拿到这道题的想法就是模为素数,那必然有原根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:\n" , ++cas); 119 int tot = 0; 120 /*P==2另外处理*/ 121 if(P==1){ 122 printf("%d %d\n" , 0,0); 123 continue; 124 } 125 if(P==2){ 126 printf("%d %d\n" , 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\n" , ans[i].first , ans[i].second); 172 } 173 } 174 return 0; 175 }
时间: 2024-10-13 12:01:13