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 }
View Code

 

posted @ 2015-06-10 22:33  idy002  阅读(325)  评论(0编辑  收藏  举报