• [BSGS][哈希]luogu P3846 可爱的质数


    https://www.luogu.org/problem/P3846

    分析

    BSGS算法,用于解决求离散对数的问题(拔山盖世(确信))

    题目要求$B^Lequiv N (mod p)$

    那么我们把形式写成这样:

    $B^{im-j}equiv N (mod p)$

    其中$m=left lceil sqrt{p} ight ceil$

    然后显然可以写成

    $B^{im}equiv NB^j (mod p)$

    显然i的取值是从1~m的,j的取值是从0~m的

    我们将所有$NB^J mod p$的取值算出来,用哈希储存j

    然后再枚举im,寻找相等的即可

    #include <iostream> 
    #include <cstdio>
    #include <cmath>
    using namespace std;
    const int Q=12255871;
    struct Hash {
        int val,id;
    }h[Q];
    int P,B,N,n;
    
    int Pow(int x,long long y) {int ans=1;for (;y;y>>=1,x=1ll*x*x%P) if (y&1) ans=1ll*ans*x%P;return ans;}
    
    void Insert(int x) {
        int val=1ll*N*Pow(B,x)%P,i=val%Q;
        while (h[i].val!=val&&h[i].id>-1) i=(i+1)%Q;
        h[i].val=val,h[i].id=x;
    }
    
    int Search(long long x) {
        int val=Pow(B,x),i=val%Q;
        while (h[i].val!=val&&h[i].id>-1) i=(i+1)%Q;
        return h[i].id;
    }
    
    int main() {
        for (int i=0;i<Q;i++) h[i].id=-1;
        scanf("%d%d%d",&P,&B,&N);
        if (B%P==0) {
            printf("no solution");
            return 0;
        }
        n=sqrt(P);if (n*n!=P) n++;
        for (int i=0;i<=n;i++) Insert(i);
        for (long long i=n;i<=P;i+=n) {
            int j=Search(i);
            if (j<0) continue;
            printf("%d",(1ll*i-j+P)%P);
            return 0;
        }
        printf("no solution");
    }
    View Code
  • 相关阅读:
    面向对象
    数据库,连接查询
    主外键,子查询
    字符串函数
    数据库。模糊查询,聚合函数,时间日期函数
    数据库。增,删,改,查
    数据库
    多窗体及菜单
    winform公共控件及其常用属性
    winform 客户端应用程序(c/s b/s)
  • 原文地址:https://www.cnblogs.com/mastervan/p/11380830.html
Copyright © 2020-2023  润新知