POJ_3243 Clever Y babystep
来源:互联网 发布:应用最广泛的编程语言 编辑:程序博客网 时间:2024/05/16 07:35
http://poj.org/problem?id=3243
题意:
和上一题一样,还是求A^x = B( mod C )的最小x值,但是这题和上题有个不同点就是
这题的C没有限制条件,也就是说这题并没有规定C必须是质数。
思路:
还是用 babystep_gaintstep算法求解。但是这题并不能用POJ_2417的算法,直接套该
算法,下面简要说明一下不能用的原因。首先我们有必要归纳一下用babystep算法解题
的步骤: (1) 、求M = ceil( sqrt(C) ) ;(2) for(i=0;i<M;i++) hash( i , A^i ) ;(3) 求D = A^M
%C;(4) 、r = 1 ; for( i = 0 ; i < M ; i++ ) ex_gcd(r , C , x , y ) ; res = x * B % C ; jj = find( res)
如果找到了这时候的jj,则答案就是i*M+jj,如果没有找到,则res = res * D % C,继续循
环查找,如果最终都没有找到,则输出无解。 在上述的步骤中,如果题目中没有告诉我们
gcd(A , C) = 1,则我们上述的方法是错误的,原因就在于第4步,求res的时候。因为如果
我们无法保证gcd(A , C) = 1 ,也就不能保证gcd(r ,C) = 1(因为D=A^M, r = D^i),所有在
用 扩展欧几里得求出r*x + C*y = gcd(r,C ) 的一个解x0之后,原方程:r*x+C*y = B的解
x = x0 * B / gcd(r,C) + i*C / gcd(r,C) ,但是我们这个时候并不能计算出gcd(r,C),因为此时
的r本来就是经过取余之后得出的,并不能直接用来求gcd,因此我们上述的普通babystep
算法就会出错了。
这样我们就要换一种处理的方法了,这里介绍一种AC大牛博客上的一种“消因子”的方法,
具体内容请看这里:AC大牛。经过上面的分析我们很清楚接下去的处理应该从哪方面着
手,就是应该从不能求出gcd(r , C)入手。一种思想就是既然无法求, 那我每次只要保证
gcd(r, C) = 1那样就可以想普通babystep一样求解了,既然要保证gcd(r,C) =1 ,而
r = (A^M)^i,因此归根到底还是要求gcd( A , C ) = 1。下面就是从AC大牛博客上参考的“消因子”
法了,每次我们 都消去A,C的一个因子,然后对B,C, D进行如下的处理:B/=tmp;C/=tmp ;
D = D* A/tmp%C ,这样经过b轮的消因子之后,gcd(A,C) = 1, 接下去我们就可以用普通
的babystep求解出方程:A^x = B'( mod C' ) 的解 res1, 原方程的解就是 res = res1 + b。
下面给出这种方法正确的简要证明;一开始我们要求的方程是:A^x = B( mod C ),也就是
求一个最小的x,使得A^x + C*y = B,通过消因子, 我们不断在方程两遍消去gcd(A,C),这
样方程就可以变成 D*A^x1 + C'*y1 = B',很简单就可以证明上式中 x = x1 + b ; y = y1 的(只要
在方程的两边分别将消去的因子乘回去等式还是保持不变的)。这样我们的问题就转化为了
求x1和y1,即D*A^x1 = B'( mod C' ),此时gcd( A , C') = 1,这样我们就可以用普通的babystep
求出上述式子的解x1,同时也就求出了x,这样本题就解决了。
但是上述的方法还是有一个bug的,也就是说,我们用babystep求出的x1>=0,所以上述的
方法只能求出x >= b的解,这样我们自然就会想到如果有一个解x < b怎么办,上述方法就会出
先错误了,因此我们这里还需要改进。考虑b的最大值是多少,考虑每次我们消去的因子数都
最小也就是2,这样我们就可以得到b的最大值就是log(C),这样我们只要保证每次log(C)之内的
解都特判一下, 就不会出现我们刚才的问题了, 所以我们要在进行上述处理之前进行一次for
循环 ,特判0 - log(C)直接的x是否能成为解,接下去再用上述的“消因子”算法。
最后不得不佩服发明这种算法的人的神奇,将O(C)复杂度的判断,分两级判断将复杂度降低
到O( sqrt(C) ),所以就是为什么叫" babystep_gaintstep "了, 哈哈。
代码:
#include<stdio.h>#include<string.h>#include<math.h>#include<stdlib.h>#define CC(m ,what) memset(m , what , sizeof(m))typedef __int64 LL ;LL A, B ,C ;const int NN = 99991 ;bool hash[NN] ;int idx[NN] , val[NN] ;void insert(int id , LL vv){ LL v = vv % NN ; while( hash[v] && val[v]!=vv){ v++ ; if(v == NN) v-=NN ; } if( !hash[v] ){ hash[v] = 1; val[v] = vv ; idx[v] = id ; }}int find(LL vv){ LL v = vv % NN ; while( hash[v] && val[v]!=vv){ v++ ; if(v == NN) v-=NN ; } if( !hash[v] ) return -1; return idx[v] ;}void ex_gcd(LL a , LL b , LL& x , LL& y){ if(b == 0){ x = 1 ; y = 0 ; return ; } ex_gcd(b , a%b , x, y) ; LL t = x ; x = y; y = t - a/b*y ;}LL gcd(LL a,LL b){ while( a%b != 0){ LL c = a ; a = b ; b = c % b ; } return b ;}LL baby_step(LL A, LL B , LL C){ LL ans = 1 ; for(LL i=0;i<=50;i++){ if(ans == B) return i ; ans = ans * A % C ; } LL tmp , d = 0 ; LL D = 1 % C ; while( (tmp=gcd(A,C)) != 1 ){ if(B % tmp) return -1 ; d++ ; B/=tmp ; C/=tmp ; D = D*A/tmp%C ; } CC( hash , 0) ; CC( idx, -1) ; CC(val , -1) ; LL M = ceil( sqrt(C*1.0) ) ; LL rr = 1 ; for(int i=0;i<M;i++){ insert(i, rr) ; rr = rr * A % C ; } LL x, y ; for(int i=0;i<M;i++){ ex_gcd(D, C , x, y) ; LL r = x * B % C; r = (r % C + C) % C ; int jj = find( r ) ; if(jj != -1){ return LL(i)*M + LL(jj) + d ; } D = D * rr % C ; } return -1 ;}int main(){ while(scanf("%I64d %I64d %I64d",&A,&C,&B) == 3){ if(A+B+C == 0 ) break ; LL res = baby_step(A,B,C) ; if( res == -1 ){ printf("No Solution\n"); continue ; } printf("%I64d\n",res); } return 0 ;}
- POJ_3243 Clever Y babystep
- POJ3243 Clever Y
- Clever Y [Bzoj 1467]
- POJ 3243 Clever Y
- 1467: Pku3243 clever Y
- bzoj1467: Pku3243 clever Y
- poj 3243 Clever Y
- POJ 3243 Clever Y BSGS
- POJ 3243:Clever Y BSGS
- poj3243:Clever Y(BSGS)
- poj3243 Clever Y【BSGS模板】
- poj3243 Clever Y 解高次同余方程
- BZOJ 1467 Pku3243 clever Y EXBSGS
- bzoj-1467 clever Y / JDFZ-2940 EXBSGS
- BZOJ_P1467/POJ_P3243 Clever Y(扩展BSGS+哈希)
- [BZOJ1467]Pku3243 clever Y(扩展BSGS)
- [BZOJ 1467]Pku3243 clever Y:扩展BSGS
- POJ 3243 Clever Y 解高次同余方程
- 基本套接字API回顾
- module_init的加载和释放
- ajax解决问题
- Abap/4操作SmartForm(1)
- SysLink Overview
- POJ_3243 Clever Y babystep
- live555 简介
- hdu1051
- 如何将psd文件切图并布局html
- C# 数组 总结
- Oracle分组小计、总计示例(grouping sets的使用)
- Google Maps地图投影全解析(3):WKT形式表示
- Flickr后继有人 “鬼城”Google+浓妆上阵
- JavaScript等比例缩放图片