bzoj 3285 离散对数解指数方程
1 /************************************************************** 2 Problem: 3285 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:756 ms 7 Memory:32072 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <cstring> 13 #include <cctype> 14 #define N 1000010 15 16 typedef long long dnt; 17 18 const int Hmod = 60793; 19 struct Hash { 20 int head[N], key[N], val[N], next[N], etot; 21 void init() { 22 etot = 0; 23 memset( head, 0, sizeof(head) ); 24 } 25 void insert( int k, int v ) { 26 int kk = k%Hmod; 27 etot++; 28 key[etot] = k; 29 val[etot] = v; 30 next[etot] = head[kk]; 31 head[kk] = etot; 32 } 33 int query( int k ) { 34 int kk = k%Hmod; 35 for( int t=head[kk]; t; t=next[t] ) 36 if( key[t]==k ) return val[t]; 37 return -1; 38 } 39 }hash; 40 41 dnt mpow( dnt a, int b, int c ) { 42 dnt rt; 43 for( rt=1; b; b>>=1,a=(a*a)%c ) 44 if( b&1 ) rt=(rt*a)%c; 45 return rt; 46 } 47 int findroot( int p ) { 48 int phi = p-1; 49 int tmp = phi; 50 int stk[50], top; 51 top = 0; 52 for( int i=2; i<=(1<<16); i++ ) { 53 if( tmp%i==0 ) { 54 stk[++top] = i; 55 do { 56 tmp/=i; 57 }while( tmp%i==0 ); 58 } 59 } 60 if( tmp!=1 ) 61 stk[++top] = tmp; 62 for( int r=1; ; r++ ) { 63 bool ok = true; 64 for( int i=1; i<=top; i++ ) { 65 if( mpow(r,phi/stk[i],p)==1 ) { 66 ok=false; 67 break; 68 } 69 } 70 if( ok ) return r; 71 } 72 } 73 dnt ind( dnt r, int a, int p ) { // ind_r(a) mod p-1 74 int m = ceil(sqrt(p-1)); 75 hash.init(); 76 dnt cur = 1; 77 for( int i=0; i<m; i++ ) { 78 if( cur==a ) return i; 79 hash.insert( cur, i ); 80 cur = (cur*r) % p; 81 } 82 dnt base; 83 base = cur = mpow(cur,p-2,p); 84 for( int i=m; i<p; i+=m,cur=(cur*base)%p ) { 85 int j = hash.query( a*cur%p ); 86 if( j!=-1 ) return i+j; 87 } 88 return -1; // impossible 89 } 90 dnt gcd( dnt a, dnt b ) { 91 return b ? gcd(b,a%b) : a; 92 } 93 void exgcd( dnt a, dnt b, dnt &d, dnt &x, dnt &y ) { 94 if( b==0 ) { 95 d=a, x=1, y=0; 96 } else { 97 exgcd(b,a%b,d,y,x); 98 y-=a/b*x; 99 } 100 } 101 dnt meq( dnt a, dnt b, dnt c ) { // ax=b mod c 102 dnt d, dd, x, y; 103 a = (a%c+c)%c; 104 b = (b%c+c)%c; 105 d = gcd(a,c); 106 if( b%d!=0 ) return -1; 107 exgcd(a/d,c/d,dd,x,y); 108 x = x*(b/d); 109 x = (x%(c/d)+(c/d))%(c/d); 110 if( x==0 ) x+=c/d; 111 return x; 112 } 113 114 dnt a, b, c, g, p, r; 115 int aa[N], bb[N], cc[N], gg[N]; 116 117 void read( int a[] ) { 118 int i; 119 char ch; 120 for( i=0; isdigit(ch=getchar()); i++ ) 121 a[i] = ch-'0'; 122 a[i] = -1; 123 } 124 dnt modulo( int a[], dnt mod ) { 125 dnt rt = 0; 126 for( int i=0; a[i]!=-1; i++ ) 127 rt = (rt*10 + a[i]) % mod; 128 return rt; 129 } 130 int main() { 131 read(aa); 132 read(bb); 133 read(cc); 134 read(gg); 135 scanf( "%lld", &p ); 136 a = modulo(aa,p-1); 137 b = modulo(bb,p-1), 138 c = modulo(cc,p); 139 g = modulo(gg,p); 140 141 if( g%p==0 || c%p==0 ) { 142 if( g%p==0 && c%p==0 ) 143 printf( "1\n" ); 144 else 145 printf( "no solution\n" ); 146 return 0; 147 } 148 r = findroot(p); 149 // fprintf( stderr, "%d\n", (int)r ); 150 dnt ans = meq( a*ind(r,g,p), ind(r,c,p)-b*ind(r,g,p), p-1 ); 151 if( ans<0 ) 152 printf( "no solution\n" ); 153 else 154 printf( "%lld\n", ans ); 155 }