http://poj.org/problem?id=3243
题意:求$a^y \equiv b \pmod{p}$最小的$y$。(0<=x, y, p<=10^9)
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <iostream> typedef long long ll; using namespace std; int gcd(int a, int b) { return b?gcd(b, a%b):a; } void exgcd(ll a, ll b, ll &d, ll &x, ll &y) { if(!b) { d=a; x=1; y=0; return; } exgcd(b, a%b, d, y, x); y-=a/b*x; } int ni(int a, int b) { static ll x, y, d; exgcd(a, b, d, x, y); return (x+b)%b; } int ipow(int a, int b, int c) { int x=1; for(; b; b>>=1, a=(ll)a*a%c) if(b&1) x=(ll)x*a%c; return x; } struct H { static const int md=3999997; bool vis[md]; int dt[md], foo[md], s[md], top; void clr() { while(top) { int x=s[top--]; vis[x]=0, dt[x]=-1; } } void add(int a, int b) { int x=a%md; while(1) { if(!vis[x] || dt[x]==a) { if(!vis[x]) s[++top]=x; vis[x]=1; dt[x]=a; foo[x]=b; break; } ++x; if(x==md) x=0; } } int find(int a) { int x=a%md; while(1) { if(!vis[x]) return -1; if(dt[x]==a) return foo[x]; ++x; if(x==md) x=0; } } }h; int a, b, mo; bool spj() { if(b==1) puts("0"); else if(!a && !b) puts("1"); else if(!b) puts("No Solution"); else return 0; return 1; } void work() { b%=mo; if(spj()) return; for(int i=0, t=1; i<30; ++i, t=(ll)t*a%mo) if(t==b) { printf("%d\n", i); return; } int a1=0, d=1, g; while((g=gcd(a, mo))!=1) { if(b%g) { puts("No Solution"); return; } ++a1, mo/=g, b/=g, d=(ll)a/g*d%mo; } d=ni(d, mo); int m=sqrt(0.5+mo); h.clr(); for(int i=0, t=(ll)b*d%mo; i<m; ++i, t=(ll)t*a%mo) h.add(t, i); for(int i=0, wn=ipow(a, m, mo), t=1; i<=m; ++i, t=(ll)t*wn%mo) { int x=h.find(t); if(x!=-1) { printf("%d\n", a1+i*m-x); return; } } puts("No Solution"); } int main() { while(scanf("%d%d%d", &a, &mo, &b) && (a|b|mo)) work(); return 0; }
拓展的大步小步= =
跪跪跪:http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4
由于$c$不一定是质数,因此不能用原来的bsgs算法
而这样的话有解但是可能不唯一。
但是还是容易想到枚举$i$解出这个方程$a^{im} x \equiv b \pmod{p}$ 然后查找$x$是否为$a^t$,然后答案就是$im+t$。
可是发现这样的解集大小为$(a^{im}, p)$,有可能很大= =无法承受....
我们来通过将方程变成一种等价形式来简化问题:
我们将式子同时除以$d=(a, p)$,得到:$\frac{a}{d} a^m \equiv \frac{b}{d} \pmod{\frac{p}{d}}$。(当然如果$b$不能整除$d$那么方程无解辣= =将$b = xxx$搞一下就可以知道辣= =)
一直进行了$t$次直到$(a, p_{t}) = 1$,令$D = a^t \frac{1}{\prod_{i=1}^{t} d_{t}}$,那么显然$(D, p_{t}) = 1$是不是辣= =
那么得到原方程的等价形式$a^h \equiv b_{t} D^{-1} \pmod{p_t}$,解出$h$那么原问题答案就是$h+t$辣= =
那么裸$bsgs$辣
可是这里要注意哦,可能存在$y<t$的情况哟,由于$t$松的上界为$log_2 p$,我们先枚举一下判断就行辣....