BSGS[bzoj2242][bzoj3122]

时间:2023-02-01 22:00:00

数论题。

操作一:直接快速幂就好了。

操作二:我用了exgcd,shy和lyz都喜欢欧拉函数。。。QAQ最后这块还写错了。

对于ax+by=gcd(a,b)的形式,我们可以把他们变成y'x+p'y=1,当方程同乘以gcd(y,p),解不变。

最后只要将解乘以倍数即可。

操作三:baby step giant step,意为先小步后大步。由费马小定理可得答案不会超过p,我们可以把答案X看作k*m+i的形式,显然当m=sqrt(p)时复杂度最优。预处理m以内的hash值存入map(今天发现map真是个好东西), 枚举k,因为ni(y^k*m)*z%p=y^i%p,当当前值存在于哈希表是,则说明找到一个合法k与合法i,计入答案。

此时有一个特殊情况,若当前hash值为一,即ni(y^k*m)===z(mod p),则i=0;

#include<cstdio>
#include<map>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int x,y,z,p;ll xx,yy;
map<ll,ll>hash;
int gcd(int a,int b)
{
  )return a;
  return gcd(b,a%b);
}
void exgcd(int a,int b,ll &x,ll &y)
{
  ){
    x=;y=;return;
  }
 exgcd(b,a%b,x,y);int t=x;x=y;y=t-a/b*y;
}
int ni(int m)
{
  -m;ll tmp=,a=y;
  while(k)
  {
    ==)
    {
      tmp=(tmp*a)%p;
    }
    a=a*a%p;k=k/;
  }
  return tmp;
}
void solve2()
{
  z=z%p;y=y%p;
  &&z==){printf("1\n");return;}
  ){printf("Orz, I cannot find x!\n");return;}
  hash.clear();
  int m=ceil(sqrt(p));
  hash[]=m+;ll e=;
  ;i<=m;i++)
  {
    e=(e*y)%p;if(!hash[e])hash[e]=i;
  }
  ll ans=-,tmp=;e=ni(m);ll T=e;
  ;i<m;i++)
  {
      if(hash[tmp*z%p])
      {
        )ans=i*m;else ans=i*m+hash[tmp*z%p];
        break;
      }
      tmp=tmp*T%p;
  }
  )printf("Orz, I cannot find x!\n");else printf("%lld\n",ans);
}
int main()
{
   int cas,ty;
    scanf("%d%d",&cas,&ty);
    while(cas--)
    {
        scanf("%d%d%d",&y,&z,&p);
        )
        {
            ,a=y;
            )
            {
              ==){
                  tmp=(tmp*a)%p;
              }
              a=a*a%p;k=k/;
            }
            printf("%lld\n",tmp);
        })
        {
            int x;if(y>p)x=gcd(y,p);else x=gcd(p,y);
            )
            {
                xx=,yy=;y=y/x;z=z/x;p=p/x;
                if(y>p) exgcd(y,p,xx,yy);else exgcd(p,y,yy,xx);
                xx=xx*z%p;
                )xx+=p;
                printf("%lld\n",xx);
            }else printf("Orz, I cannot find x!\n");
        })
        {
            solve2();
        }

    }
 } 

bzoj2242

07/23

3122这道题其实hzw的博客里已经写的很详尽了,但是蒟蒻还是理解了好久。

可能数论题的每一步操作每一个特判都很精妙,也可能是个人题目做得太少TAT

               if(x1==t){
            printf("1\n");continue;
        }
        )
        {
          if(b==t)printf("2\n");else printf("-1\n");
          continue;
        }

首先这里开场的两个特判;

if(a==1)
  {
     printf("%d\n",calc1());
     continue;
  }

其次是判断a==1的情况,我有尝试把它删去试试,发现这样就wa了,因为求数列的时候a不能为1;

对于a==1的可行情况,xn=x1+(n−1)b===(同余)t,我们把x1移项,做一下exgcd(b,p,x,y),(当然还要判一下它们的gcd是否被t-x1整除的情况);当然别忘了x可能<0,当然也别忘了x+1(x==n-1)。

当a>2时,这时的确需要一些数学姿势!

通项公式(我不会推啊。。。只能请教班上的数竞大神了)

“告诉你x1的值,x2=ax1+b,……,Xn=a*Xn-1+b,a与b的值已知,求数列通项公式,只要用x1,a,b表示就行。”BSGS[bzoj2242][bzoj3122]

Xn=a^(n−1)*x1+b*A(n−1)−1/a−1(mod p)=t...........不会latex啦

我们就可以这样做:把所有常数丢到右边,与a^(n-1)相关的留在左边,

设c为a−1的逆元设c为a−1的逆元   (x1+bc)an−1=bc+t(mod p)

此时需要注意的是,系数A=x1+bc,系数B=bc+t,它们都有可能大于p了,所以这时候还需要特判:(这道题特判好多)

1.如果系数A%p==0,那么B也要是p的倍数才行

2.设a^(n-1)=S,做一遍exgcd(A,p,x,y),要求Ax+py=B嘛,只要乘以系数就好了,另外得到的x就可以代入BSGS了

好了。。。。。。。。干了这么多事情

终于可以用上窝萌亲爱的baby step giant step了!

第二遍写了,蛮好理解的...map蛮好用的+2

#include<cstdio>
#include<map>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int cas;
ll p,a,b,x1,t,x,y;
ll quick(ll x,ll b)
{
  x=x%p;
  ll k=b,tmp=,a=x;
  )
  {
    ==)
    {
      tmp=tmp*a%p;
    }
    a=a*a%p;k/=;
  }
  return tmp;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    ){
      x=;y=;return a;
    }
    ll tmp=exgcd(b,a%b,x,y);
    ll t=x;x=y;y=t-a/b*y;
    return tmp;
}
ll calc1()
{
    ll C=(t-x1+p)%p,x,y;
    ll day=exgcd(b,p,x,y);
    ;
    C/=day;
    x=x*C%p;
    )x+=p;
    ;
}
map<ll,int>mp;
ll bsgs(ll A,ll B,ll C)
{
   A%=C;
   )
   {
      );;//MARK
   }
   ;
   ll t=,I=,Im=quick(A,C--m);
   mp.clear();mp[]=m+;
   ;i<m;i++)
   {
       t=t*A%C;if(!mp[t])mp[t]=i;
   }
   ;k<m;k++)
   {
       int i=mp[B*I%C];
       if(i)
       {
          )i=;//printf("%d %d %lld\n",k,m,B);
          return m*k+i;
       }
       I=I*Im%C;
   }
   ;
}
ll calc2()
{
  ll c=quick(a-,p-);
  ll C=(t+b*c)%p;
  ll A=(x1+b*c)%p;
  ll t=exgcd(A,p,x,y);
  ;
  C/=A;
  if(x<p)x=x%p+p;
  t=bsgs(a,x*C%p,p);
  //printf("===%lld\n",t);
  );;
}
int main()
{
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t);
        if(x1==t){
            printf("1\n");continue;
        }
        )
        {
          if(b==t)printf("2\n");else printf("-1\n");
          continue;
        }
        )
        {
           printf("%d\n",calc1());
           continue;
        }
        printf("%lld\n",calc2());
    }
} 

bzoj3122

BSGS[bzoj2242][bzoj3122]的更多相关文章

  1. &lpar;ex&rpar;BSGS题表

    学了一下BSGS大概知道他是什么了,但是并没有做什么难题,所以也就会个板子.普通的BSGS,我还是比较理解的,然而exBSGS我却只理解个大概,也许还会个板子......(这个东西好像都会有一群恶心的 ...

  2. 【BZOJ2242】计算器(BSGS,快速幂)

    [BZOJ2242]计算器(BSGS,快速幂) 题面 BZOJ 洛谷 1.给定y.z.p,计算y^z mod p 的值: 2.给定y.z.p,计算满足xy ≡z(mod p)的最小非负整数x: 3.给 ...

  3. 【BZOJ3122】随机数生成器(BSGS,数论)

    [BZOJ3122]随机数生成器(BSGS,数论) 题面 BZOJ 洛谷 题解 考虑一下递推式 发现一定可以写成一个 \(X_{i+1}=(X_1+c)*a^i-c\)的形式 直接暴力解一下 \(X_ ...

  4. 【BZOJ3122】&lbrack;Sdoi2013&rsqb;随机数生成器 BSGS&plus;exgcd&plus;特判

    [BZOJ3122][Sdoi2013]随机数生成器 Description Input 输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数.   接下来T行,每行有五个整数p,a,b, ...

  5. 【BZOJ2242】&lbrack;SDOI2011&rsqb;计算器 BSGS

    [BZOJ2242][SDOI2011]计算器 Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ ...

  6. 【bzoj3122】&colon; &lbrack;Sdoi2013&rsqb;随机数生成器 数论-BSGS

    [bzoj3122]: [Sdoi2013]随机数生成器 当a>=2 化简得 然后 BSGS 求解 其他的特判 : 当 x=t  n=1 当 a=1  当 a=0 判断b==t /* http: ...

  7. 【bzoj2242】&colon; &lbrack;SDOI2011&rsqb;计算器 数论-快速幂-扩展欧几里得-BSGS

    [bzoj2242]: [SDOI2011]计算器 1.快速幂 2.扩展欧几里得(费马小定理) 3.BSGS /* http://www.cnblogs.com/karl07/ */ #include ...

  8. 【BZOJ-3122】随机数生成器 BSGS

    3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1362  Solved: 531[Submit][Sta ...

  9. 【BZOJ2242】【SDoi2011】计算器 快速幂&plus;EXGCD&plus;BSGS

    Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...

随机推荐

  1. Centos7数据实时同步

    Rsync+inotify 功能要求 通过rsync+inotify将数据库指定目录实时同步到备份服务器. 环境说明 M:192.168.10.11 数据库服务器 S:192.168.10.13 备份 ...

  2. 新概念英语(1-133)Sensational news&excl;

    Lesson 133 Sensational news! 爆炸性新闻! Listen to the tape then answer this question. What reason did Ka ...

  3. 501&period; Find Mode in Binary Search Tree

    Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred ...

  4. 高效求a的n次幂的算法

    代码: public class A的N次幂 { public static void main(String[] args) { int a = 2; int n = 60; long t = Sy ...

  5. 821&period; 字符的最短距离 c&plus;&plus;实现方法

    1.题目描述 给定一个字符串 S 和一个字符 C.返回一个代表字符串 S 中每个字符到字符串 S 中的字符 C 的最短距离的数组. 示例 1: 输入: S = "loveleetcode&q ...

  6. Linux 硬件信息命令

    # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数cat /proc/cpuinfo| g ...

  7. MySQL 两个死锁样例

    [引子] 从事MySQL-DBA这一行也有些年头了,想对新人说,在分析死锁问题时应该还要考虑到有一个叫请求队列的“概念”.之所以 在这里提这个不是因为新手不知道,而是有时候会自然而然的想不到. 不信的 ...

  8. bzoj 2342 &lbrack;Shoi2011&rsqb;双倍回文(manacher,set)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2342 [题意] 求出形如w wR w wR的最长连续子串. [思路] 用manache ...

  9. 三分搜索-ZOJ LightBulb

    开始算法基础学习的第一天 今天学习的内容是三分搜索 相对来说很基础的内容(还是觉得脑子不够用) 三分搜索主要用于凸函数查找极大值. (盗个图) 如图所示 若要查找该函数的最大值 可以考虑和二分法一样的 ...

  10. &lbrack; Linux 命令 &rsqb; grep

    一.grep是什么? Linux grep命令是用于查找文件里符合条件行的shell命令. 二.为什么要使用grep? 在查找文件内容时候,通过使用grep指定条件,可以快速定位到文件里字符串所在的行 ...