zoukankan      html  css  js  c++  java
  • BSGS算法初探

    前言

    \(BSGS\)算法,全称\(Baby\ Step\ Giant\ Step\),即大小步算法。某些奆佬也称其为(Ba)(Shan)(Gai)(Shi)算法。

    它的主要作用是求解形式如\(x^t\equiv y(mod\ MOD)\)的式子中\(t\)的值\((gcd(x,MOD)=1)\)

    而且,它是一个简单易懂的算法(毕竟连我这样的数学渣渣都能理解)。

    一个简单的性质

    首先,我们需要知道一个简单的性质。

    费马小定理可得,\(x^{MOD-1}\equiv1(mod\ MOD)\)

    因此,当\(t\ge MOD-1\)时,会出现一个循环节。

    于是我们就能保证答案\(t\)如果存在,则必然\(<MOD-1\)

    这是一个简单而又重要的性质。

    \(BSGS\)算法的主要思想

    \(BSGS\)算法的主要思想就是两个字:分块(提到分块就要\(\%\)一波分块奆佬\(hl666\))。

    根据分块思想,我们设一个变量\(Size=\sqrt{MOD}\)(注意,此处要用\(ceil\)函数向上取整,这样才能保证\(Size*Size\ge MOD\),不然可能会遗漏答案)。

    不难发现,此时的\(t\)可以表示为\(i*Size-j\)\(i,j\)均为非负整数且\(j<Size\))。

    那么原式就被转化成了\(x^{i*Size-j}\equiv y(mod\ MOD)\)

    移项得\(x^{i*Size}\equiv x^j*y(mod\ MOD)\)

    然后怎么处理呢?

    我们可以对\(x^j*y\)的值进行一波预处理,用一个\(map\)存储下来。

    然后枚举\(i\),判断\(x^{i*Size}\)的值是否存在即可。

    当找到一个合法的\(i\)后,最终的答案就是\(i*Size-j\)

    时间复杂度分析

    预处理的时间复杂度显然是\(O(j)\)的,枚举\(i\)的时间复杂度显然是\(O(i)\)的。

    又由于\(i\)\(j\)都是\(O(\sqrt N)\)大小的,所以总复杂度也是\(O(\sqrt N)\)级别的,是一个比较优秀的算法。

    代码

    map<int,int> s;//定义一个map
    inline int BSGS(int x,int y,int MOD)//对于一个式子x^t=y(mod MOD),求出t的值
    {
    	register int i,t=1,base,Size=ceil(sqrt(MOD));//注意此处要用ceil函数向上取整
    	for(i=0;i<=Size;++i) s[1LL*t*y%MOD]=i,base=t,t=1LL*t*x%MOD;//预处理将(x^j)*y的值全部用map存下对应的j,并用base存储下x^Size
    	for(t=base,i=1;i<=Size;++i,t=1LL*t*base%MOD)//枚举i,每次将t乘上x^Size 
    		if(s[t]) return i*Size-s[t];//找到一个合法的i,则答案就是i*Size-j
    	return 0;//无解返回0
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    linux sysfs (2)
    微软——助您启动云的力量网络虚拟盛会
    Windows Azure入门教学系列 全面更新啦!
    与Advanced Telemetry创始人兼 CTO, Tom Naylor的访谈
    Windows Azure AppFabric概述
    Windows Azure Extra Small Instances Public Beta版本发布
    DataMarket 一月内容更新
    和Steve, Wade 一起学习如何使用Windows Azure Startup Tasks
    现实世界的Windows Azure:与eCraft的 Nicklas Andersson(CTO),Peter Löfgren(项目经理)以及Jörgen Westerling(CCO)的访谈
    正确使用Windows Azure 中的VM Role
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BSGS.html
Copyright © 2011-2022 走看看