# 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;
24     }
25     void insert( int k, int v ) {
26         int kk = k%Hmod;
27         etot++;
28         key[etot] = k;
29         val[etot] = v;
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() {
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  阅读(270)  评论(0编辑  收藏  举报