联系:http://acm.hdu.edu.cn/showproblem.php?pid=2815

意甲冠军:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvb29vb29vb29l/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

思路:与上题不同。这道题不要求m是素数。是利用扩展Baby Step Giant Step算法求离散对数。

下面转载自:AekdyCoin

【扩展Baby Step Giant Step】



【问题模型】

求解

A^x = B (mod C) 中 0 <= x < C 的解,C 无限制(当然大小有限制……)



【写在前面】

这个问题比較麻烦。眼下网络上流传很多版本号的做法,只是大部分已近被证明是全然错误的!



这里就不再累述这些做法。以下是我的做法(有问题欢迎提出)



以下先给出算法框架。稍后给出具体证明:



(0) for i = 0 -> 50 if(A^i mod C == B) return i    O(50)

(1)  d<- 0                D<- 1 mod C

while((tmp=gcd(A,C))!=1)

{

if(B%tmp)return -1; // 无解!

++d;

C/=tmp;

B/=tmp;

D=D*A/tmp%C;

}

(2) m = Ceil ( sqrt(C) ) //Ceil是必要的     O(1)

(3) for i = 0 -> m 插入Hash表(i, A^i mod C)  O( m)

(4) K=pow_mod(A,m,C)

for i = 0 -> m

解 D * X = B (mod C) 的唯一解 (假设存在解。必定唯一!)

之后Hash表中查询,若查到(如果是 j),则 return i * m + j + d

否则

D=D*K%C,继续循环

(5) 无条件返回 -1 ;//无解!





以下是证明:

推论1:

A^x = B(mod C)

等价为

A^a  * A^b  = B ( mod C)   (a+b) == x       a,b >= 0



证明:

A^x = K * C + B (模的定义)

A^a * A^b = K*C + B( a,b >=0, a + b == x)

所以有 

A^a * A^b = B(mod C)

推论 2:

令 AA * A^b = B(mod C)

那么解存在的必要条件为:  能够得到至少一个可行解 A^b = X (mod C)

使上式成立

推论3

AA * A^b = B(mod C)

中解的个数为 (AA,C)

由推论3 不难想到对原始Baby Step Giant Step的改进

For I = 0 -> m

For any solution that AA * X = B (mod C)

If find X

Return I * m + j

而依据推论3,以上算法的复杂度实际在 (AA,C)非常大的时候会退化到差点儿O(C)

归结原因,是由于(AA,C)过大,而就是(A,C)过大

于是我们须要找到一中做法,能够将(A,C)降低。并不影响解



以下介绍一种“消因子”的做法



一開始D = 1 mod C

进行若干论的消因子,对于每次消因子

令 G = (A,C[i])  // C[i]表示经过i轮消因子以后的C的值

假设不存在 G | B[i]  //B[i]表示经过i轮消因子以后的B的值

直接返回无解

否则

B[i+1] = B[i] / G

C[i+1] = C[i] / G

D = D * A / G



详细实现仅仅须要用若干变量,细节參考代码



如果我们消了a'轮(如果最后得到的B,C分别为B',C')

那么有

D * A^b = B' (mod C')



于是能够得到算法



for i = 0 -> m

解 ( D* (A^m) ^i ) * X = B'(mod C')

因为 ( D* (A^m) ^i , C') = 1 (想想为什么?)

于是我们能够得到唯一解

之后的做法就是对于这个唯一解在Hash中查找



这样我们能够得到b的值,那么最小解就是a' + b !!



如今问题大约已近攻克了,但是细心看来,事实上还是有BUG的。那就是

对于

A^x = B(mod C)

假设x的最小解< a',那么会出错

而考虑到每次消因子最小消 2

故a'最大值为log(C)

于是我们能够暴力枚举0->log(C)的解,若得到了一个解,直接返回

否则必定有 解x > log(C)



PS.以上算法基于Hash 表,假设使用map等平衡树维护,那么复杂度会更大

(转载结束)

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <ctype.h>
#include <algorithm>
#include <string>
#include <set>
#define PI acos(-1.0)
#define maxn 1000005
#define INF 0x7fffffff
#define eps 1e-8
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
int extend_gcd(int a, int b, int &x, int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int r=extend_gcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return r;
}
LL pow_mod(LL aa,LL ii,LL nn)
{
if(ii==0)
return 1%nn;
LL temp=pow_mod(aa,ii>>1,nn);
temp=temp*temp%nn;
if(ii&1)
temp=temp*aa%nn;
return temp;
}
struct b_step
{
int i,m;
} bb[maxn];
int inval(int a,int b,int n)
{
int e,x,y;
extend_gcd(a,n,x,y);
e=((LL)x*b)%n;
return e<0? e+n:e;
}
bool cmp(b_step a,b_step b)
{
return a.m==b.m?a.i<b.i:a.m<b.m;
}
int BiSearch(int m,LL num)
{
int low=0,high=m-1,mid;
while(low<=high)
{
mid=(low+high)>>1;
if(bb[mid].m==num)
return bb[mid].i;
if(bb[mid].m<num)
low=mid+1;
else
high=mid-1;
}
return -1;
}
int giant_step_baby_step(LL b,LL n,LL p)
{
LL tt=1%p;
for(int i=0; i<100; i++)
{
if(tt%p==n)
return i;
tt=((LL)tt*b%p);
}
LL D=1%p;
int d=0,temp;
while((temp=__gcd(b,p))!=1)
{
if(n%temp)
return -1;
d++;
n/=temp;
p/=temp;
D=((b/temp)*D)%p;
}
int m=(int)ceil(sqrt((double)(p)));
bb[0].i=0,bb[0].m=1%p;
for(int i=1; i<=m; i++)
{
bb[i].i=i;
bb[i].m=bb[i-1].m*b%p;
}
sort(bb,bb+m+1,cmp);
int top=1;
for(int i=1; i<=m; i++)
if(bb[i].m!=bb[top-1].m)
bb[top++]=bb[i];
int bm=pow_mod(b,m,p);
for(int i=0; i<=m; i++)
{
int tmp=inval(D,n,p);
if(tmp>=0)
{
int pos=BiSearch(top,tmp);
if(pos!=-1)
return i*m+pos+d;
}
D=((LL)(D*bm))%p;
}
return -1;
}
int main()
{
int b,p,n;
while(~scanf("%d%d%d",&b,&p,&n))
{
if(n>=p)
{
puts("Orz,I can’t find D!");
continue;
}
int ans=giant_step_baby_step(b,n,p);
if(ans==-1)
puts("Orz,I can’t find D!");
else printf("%d\n",ans);
}
return 0;
}

版权声明:本文博主原创文章。博客,未经同意不得转载。

HDU 2815 Mod Tree 离散对数 扩张Baby Step Giant Step算法的更多相关文章

  1. HDU 2815 Mod Tree (扩展 Baby Step Giant Step )

    Mod Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  2. hdu 2815 Mod Tree (exBSGS)

    http://acm.hdu.edu.cn/showproblem.php?pid=2815 //解 K^D ≡ N mod P #include<map> #include<cma ...

  3. hdu 2815 : Mod Tree 【扩展BSGS】

    题目链接 直接用模板好了.实在不行,反正有队友啊~~~~ #include<bits/stdc++.h> using namespace std; typedef long long LL ...

  4. hdu 2815 Mod Tree 高次方程,n不为素数

    Accepted 406MS 8576K 2379 B C++/** 这里加了一点限制,,大体还是一样的,, **/ #include <iostream> #include <cs ...

  5. HDU 2815 Mod Tree

    不会,先搁着…… http://blog.csdn.net/acm_cxlove/article/details/7832197

  6. HDU 2815 扩展baby step giant step 算法

    题目大意就是求 a^x = b(mod c) 中的x 用一般的baby step giant step 算法会超时 这里参考的是http://hi.baidu.com/aekdycoin/item/2 ...

  7. 解高次同余方程 (A^x=B(mod C),0<=x<C)Baby Step Giant Step算法

    先给出我所参考的两个链接: http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4 (AC神,数论帝  扩展Baby Step Gian ...

  8. POJ 3243 Clever Y (求解高次同余方程A^x=B(mod C) Baby Step Giant Step算法)

    不理解Baby Step Giant Step算法,请戳: http://www.cnblogs.com/chenxiwenruo/p/3554885.html #include <iostre ...

  9. 【学习笔记】Baby Step Giant Step算法及其扩展

    1. 引入 Baby Step Giant Step算法(简称BSGS),用于求解形如\(a^x\equiv b\pmod p\)(\(a,b,p\in \mathbb{N}\))的同余方程,即著名的 ...

随机推荐

  1. Windows8和MacOS10.9双系统安装及Mac经常使用软件安装--联想E49A

    前提 本篇内容所描写叙述的内容仅仅适合联想E49A笔记本,经过本篇的内容之后,对于Mac OS 10.9的使用达到正常工作使用的标准,完美度已经比較好了. 结果例如以下:显卡.网卡(RTL8168). ...

  2. POJ 3076 Sudoku (dancing links)

    题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是依照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- ...

  3. 利用linux BT5来破解无线 破解无线

    下面是自己整理的详细步骤,版权小冯全部. 一.提前准备好bt5的ISO镜像文件.和虚拟机,提前把虚拟机安装好.然后进行安装bt5. 二.进入页面,点击statx.进入可视化界面. 三.进入主界面后.下 ...

  4. NSDictionary、NSMutableDictionary基本使用

    郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...

  5. html练习(5)

    这个练习主要简单的展示了据对定位和相对定位: 在此说下html的定位: 1.static定位 这个是默认的方式.对static而言.left和right是不生效的. 2.relative定位(相对定位 ...

  6. C++实现链栈的基本操作

    之前对顺序栈写了基本操作,认为有必要也动手练练栈的链表实现. 对于链栈,一般不会出现栈满的情况. 链栈头文件定义例如以下: #ifndef CSTOCK_H_ #define CSTOCK_H_ ty ...

  7. php-GD库的函数(二)

    <?php //imagecopy — 拷贝图像的一部分粘贴到某图像上 /*bool imagecopy ( resource $dst_im , resource $src_im , int ...

  8. 大话设计模式C++达到-文章12章-外观模式

    一.UML画画 关键词:添加Facade层. 二.概念 外观模式:为子系统中的一组接口提供一个一致的界面.此模式定义了一个高层接口,这个接口使得这一子系统更加easy使用. 三.说明 Q:外观模式在什 ...

  9. iOS Dev (59) 高度自适应的UITextView

    iOS Dev (59) 高度自适应的UITextView 作者:阿锐 地址:http://blog.csdn.net/prevention - 例如以下 _inputTextView 为一个 UIT ...

  10. Android 之流媒体播放器,广播侧下方这么简单。

    没有其他的.希望从事流媒体开发案例.还承诺提供朋友博客.上个星期.制定出最后一点机会. 在这里,与大家分享. 首先要明白的概念:什么是流媒体?转载请注明出处http://blog.csdn.net/g ...