• bzoj 3122 : [Sdoi2013]随机数生成器 BSGS


    BSGS算法

    转自:http://blog.csdn.net/clove_unique

    问题

    给定a,b,p,求最小的非负整数x,满足$a^x≡b(mod p)$

    题解

    这就是经典的BSGS算法,方法如下:
    令$x=im−j$,$m=⌈sqrt{p}⌉$,则$a^{im−j}≡b(mod p)$
    移项,得$(a^m)^i≡ba^j(mod p) $
    首先,从$0−m$枚举$j$,将得到的$ba^j$的值存入hash表;
    然后,从$1−m$枚举$i$,计算$(a^m)^i$,查表,如果有值与之相等,则当时得到的$im−j$是最小值。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<map>
      6 #include<cmath>
      7 #define int long long
      8 using namespace std;
      9 int p;
     10 int pw(int x,int y)
     11 {
     12     int lst=1;
     13     while(y)
     14     {
     15         if(y&1)lst=lst*x%p;
     16         y>>=1;
     17         x=x*x%p;
     18     }
     19     return lst;
     20 }
     21 int xx,yy;
     22 void exgcd(int a,int b)
     23 {
     24     if(b==0)
     25     {
     26         xx=1;yy=0;
     27         return ;
     28     }
     29     exgcd(b,a%b);
     30     int tmp=xx;
     31     xx=yy;
     32     yy=tmp-(a/b)*yy;
     33     return ;
     34 }
     35  
     36 map<int,int>mp;
     37 int work(int a,int b)
     38 {
     39      int m=ceil(sqrt(p));
     40      mp.clear();
     41      int now=1;
     42      mp[now*b%p]=0;
     43      for(int i=1;i<=m;i++)
     44      {
     45         now=now*a%p;
     46         mp[now*b%p]=i;
     47      }
     48      int tmp=1;
     49      for(int i=1;i<=m;i++)
     50      {
     51         tmp=tmp*now%p;
     52         if(mp[tmp])
     53         {
     54             return  i*m-mp[tmp];
     55         }
     56      }
     57      return -1;
     58 }
     59 int a,b,x1,t;
     60 signed main()
     61 {
     62     int cas;
     63     scanf("%lld",&cas);
     64     while(cas--)
     65     {
     66         scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t);
     67         if(x1==t)
     68         {
     69             puts("1");
     70             continue;
     71         }
     72         if(a==0)
     73         {
     74             if(x1==t)puts("1");
     75             else if(b==t)puts("2");
     76             else puts("-1");
     77             continue;
     78         }
     79         if(a==1)
     80         {
     81             if(!b)
     82             {
     83                 if(x1==t)puts("1");
     84                 else puts("-1");
     85                 continue;
     86             }
     87             exgcd(b,p);
     88             int tmp=(t-x1+p)%p;
     89             xx=((xx*tmp%p)+p)%p;
     90             xx++;
     91             printf("%lld
    ",xx);
     92         }
     93         else
     94         {
     95             int c=pw(a-1,p-2);
     96             int t1=(x1+b*c)%p,t2=p,t3=(b*c+t)%p;
     97             exgcd(t1,t2);
     98             xx=(xx%p+p)%p;
     99             xx=(xx*t3)%p;
    100             int ans=work(a,xx);
    101             if(ans!=-1)printf("%lld
    ",ans+1);
    102             else printf("%lld
    ",ans);
    103         }
    104     }
    105     return 0;
    106 }
  • 相关阅读:
    字典
    字符串常用的方法
    切片,集合、文件处理
    蓝桥杯练习 Day6 题解
    spoj-ORDERS
    spoj-SUBSUMS
    spoj
    spoj --- ABCDEF
    C. Andryusha and Colored Balloons
    B. The Meeting Place Cannot Be Changed
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6600520.html
Copyright © 2020-2023  润新知