zoukankan      html  css  js  c++  java
  • BSGS

    求解a^x=b(mod p),p为质数时,直接bsgs就可以了。

    将x写作km-j,m=sprt(p)时复杂度最优,a^(km)=ba^j(mod p),我们预先求出a^j(j=0~m-1)存入map,然后穷举k=1~p/m,如果map中有值,返回km-cnt[]就可以了。

    bzoj4128 Matrix

    题目大意:a^x=b(mod p),a、b为矩阵。

    思路:bsgs直接求就可以了,因为不需要求逆,所以方便许多。(注意map要重定义比较符号)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<cmath>
    using namespace std;
    struct use{
        int num[100][100];
        void init()
        {
            int i,j;
            for (i=0;i<100;++i)
              for (j=0;j<100;++j) num[i][j]=1;
        }
        bool operator == (const use & a)const
        {
            int i,j;
            for (i=0;i<100;++i)
              for (j=1;j<100;++j)
                if (num[i][j]!=a.num[i][j]) return false;
            return true;
        }
        bool operator < (const use & a)const
        {
            int i,j;
            for (i=0;i<100;++i)
              for (j=0;j<100;++j)
              {
                if (num[i][j]<a.num[i][j]) return true;
                if (num[i][j]>a.num[i][j]) return false;
              }
            return false;
        }
        bool operator > (const use & a)const
        {
            int i,j;
            for (i=0;i<100;++i)
              for (j=0;j<100;++j)
              {
                if (num[i][j]>a.num[i][j]) return true;
                if (num[i][j]<a.num[i][j]) return false;
              }
            return false;
        }
    }a,b;
    map <use,int> cnt;
    int n,p;
    use calc(use m1,use m2)
    {
        int i,j,k;
        use m3;
        for (i=1;i<=n;++i)
          for (j=1;j<=n;++j)
          {
              m3.num[i][j]=0;
            for (k=1;k<=n;++k) m3.num[i][j]=(m3.num[i][j]+(m1.num[i][k]*m2.num[k][j])%p)%p;
          }
        return m3;
    }
    int bsgs()
    {
        use m1,m2;
        int i,j,m;
        m1=b;m=sqrt(p);cnt[m1]=1;
        for (i=1;i<m;++i)
        {
            m1=calc(m1,a);cnt[m1]=i+1;
        }
        m1=a;for (i=2;i<=m;++i) m1=calc(m1,a);
        m2=m1;
        for (i=1;i<=p/m;++i)
        {
            if (cnt[m2]!=0) return i*m-cnt[m2]+1;
            m2=calc(m1,m2);
        }
        return 0;
    }
    int main()
    {
        int i,j;
        scanf("%d%d",&n,&p);
        for (i=1;i<=n;++i)
          for (j=1;j<=n;++j) scanf("%d",&a.num[i][j]);
        for (i=1;i<=n;++i)
          for (j=1;j<=n;++j) scanf("%d",&b.num[i][j]);
        printf("%d
    ",bsgs());
    }
    View Code

    bzoj3122 随机数生成器

    题目大意:ci=(a * ci-1 + b) %p,ci=t的最小i值,如果没有输出-1。

    思路:求出ci的通项公式,ci=(a^(ans-1)x1+a^(ans-2)b+...+a^0b)%p=(x1+b/(a-1))*a^(n-1)-b/(a-1),发现,如果a!=0&&a!=1,那么就是bsgs了;如果a=0,就要判断b能否%p=t,如果可以,就是2天,否则-1;如果a=1,就是拓展欧几里德了,但是要注意=t,而不是=1,所以答案是t/d*x%p(注意%p,还有之前求出来的x可能为负,也要转化)。如果答案是0就输出p。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<cmath>
    #define LL long long
    using namespace std;
    LL p;
    map<LL,int> cnt;
    void gcd(LL a,LL b,LL &d,LL &x,LL &y){
        if (!b){d=a;x=1LL;y=0LL;return;}
        else{gcd(b,a%b,d,y,x);y-=a/b*x;}
    }
    LL mi(LL x,LL y){
        if (y==0) return 1LL;
        if (y==1) return x%p;
        LL mm=mi(x,y/2);
        if (y%2) return mm*mm%p*x%p;
        else return mm*mm%p;
    }
    LL calc(LL a,LL b,LL p){
        LL i,e=1LL,v,m=(LL)sqrt(p+0.5);
        cnt.clear();
        for (i=1;i<=m;++i){
            e=e*a%p;cnt[e*b%p]=i;
        }for (v=e,i=1;i<=p/m;++i){
            if (cnt.count(v)) return i*m-cnt[v];
            v=v*e%p;
        }return -2;
    }
    int main(){
        int ti;LL j,a,b,x1,t,d,x,y;scanf("%d",&ti);
        while(ti--){
          scanf("%I64d%I64d%I64d%I64d%I64d",&p,&a,&b,&x1,&t);
          x1%=p;t%=p;
          if (t==x1){printf("1
    ");continue;}
          if (a==1){
              t=(t-x1+b+p)%p;gcd(b,p,d,x,y);x=(x%p+p)%p;
              if (t%d) printf("-1
    ");
              else printf("%I64d
    ",(t=t/d*x%p)==0?p:t);
          }else{
              if (a==0){
                  if (b%p==t) printf("2
    ");
                  else printf("-1
    ");
              }else{
                 j=mi((a-1LL+p)%p,p-2);
                x=(x1+b*j%p)%p;y=(t+b*j%p)%p*mi(x,p-2)%p;
              x=calc(a,y,p);
              printf("%I64d
    ",(x+1==0?p:x+1));
            }
          }
        }
    }
    View Code
  • 相关阅读:
    ue4 socket
    ue4动画蓝图
    localStorage 用法
    关于textarea中换行、回车、空格的识别与处理
    git忽略某些文件提交
    动态加载js文件
    H5 App页面 绝对定位 软键盘弹出时顶起底部按钮
    Android软键盘弹出时把布局顶上去的解决方法
    javascript 事件委托 和jQuery事件绑定on、off 和one
    escape()、encodeURI()、encodeURIComponent()区别详解
  • 原文地址:https://www.cnblogs.com/Rivendell/p/4614514.html
Copyright © 2011-2022 走看看