• 2019牛客多校第五场generator2——BSGS&&手写Hash


    题目

    几乎原题 BZOJ3122题解

    分析

    先推一波公式,然后除去特殊情况分类讨论,剩下就是形如 $a^i equiv b(mod p)$ 的方程,可以使用BSGS算法。

    在标准的BSGS中,内外层循环都是 $sqrt p$,题目查询 $m$ 次,$m leq 1000$,$ p leq 10^9$,这样总时间复杂度为 $O(m sqrt p)$,勉强能接受。据说使用读入优化和手写哈希还是能过得,可见Cls的代码%%%

    仔细想一下,由于BSGS分成两步,其中第一步是建立 $a$ 的幂次方的表,而题恰好是 $a,p$相同下的一组询问,所以这一部分可以与处理。

    显然,我们应该对这部分分大点,第二步就会小写(因为积一定),

    如分成 $sqrt {mp} imes sqrt{frac{p}{m}}$(前面是预处理时间,后面是每次查询的时间)

    也可以是 $frac{p}{1000} imes 1000$,总之,要是预处理部分大一点。

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,a,n) for(int i=n;i>=a;i--)
    #define pb push_back
    #define mp make_pair
    #define FI first
    #define SE second
    #define maxn 100000
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef vector<int> vi;
    typedef double db;
      
    int mod;
    int m=1000;
      
    const int M=12000005;
    int hs[M],head[M],nxt[M],id[M],top;
    void insert(int x,int y)
    {
        int k=x%M;
        hs[top]=x,id[top]=y,nxt[top]=head[k],head[k]=top++;
    }
    int find(int x)
    {
        int k=x%M;
        for(int i=head[k];i!=-1;i=nxt[i]) if(hs[i]==x) return id[i];
        return -1;
    }
      
    int BSGS(int a,int b,int n)
    {
        if(b==1) return 0;
        ll p=1;
        int ans=inf;
        rep(i,0,m)
        {
            int id=find(1ll*p*b%n);
            if(id!=-1) ans=min(ans,id-i);
            p=p*a%mod;
        }
        if(ans==inf) return -1;
        return ans;
    }
      
    ll qp(ll a,ll k)
    {
        ll res=1;
        while(k)
        {
            if(k&1) res=res*a%mod;
            a=a*a%mod;
            k>>=1;
        }
        return res;
    }
    ll _inv(ll x) {return qp(x,mod-2);}
      
    int main()
    {
        int CAS; scanf("%d",&CAS);
        while(CAS--)
        {
            ll N; int x0,a,b; scanf("%lld%d%d%d%d",&N,&x0,&a,&b,&mod);
            memset(head,-1,sizeof head); top=1;
      
            int bn=(mod+m-1)/m;
            int aA=qp(a,m),pw=aA;
            rep(i,1,bn)
            {
                if(find(pw)==-1) insert(pw,i*m);
                pw=1ll*pw*aA%mod;
            }
            int Q; scanf("%d",&Q);
            while(Q--)
            {
                int v; scanf("%d",&v);
                if(a==0)
                {
                    if(v==x0) puts("0");
                    else if(v==b)
                    {
                        if(N==1) puts("-1");
                        else puts("1");
                    }
                    else puts("-1");
                }
                else if(a==1)
                {
                    if(b==0)
                    {
                        if(v==x0) puts("0");
                        else puts("-1");
                    }
                    else
                    {
                        ll n=1ll*(v+mod-x0)*_inv(b)%mod;
                        if(n>=N) puts("-1");
                        else printf("%lld
    ",n);
                    }
                }
                else
                {
                    v=(1ll*(a-1)*v+b)%mod;
                    int X=(1ll*(a-1)*x0+b)%mod;
                    if(X==0)
                    {
                        if(v==0) puts("0");
                        else puts("-1");
                    }
                    else
                    {
                        v=1ll*v*_inv(X)%mod;
                        if(v==0) puts("-1");
                        else
                        {
                            int n=BSGS(a,v,mod);
                            if(n>=N) puts("-1");
                            else printf("%d
    ",n);
                        }
                    }
                }
            }
        }
        return 0;
    }

    参考链接:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=41008097

  • 相关阅读:
    获取动态类型变量的属性值
    C#项目实例中读取并修改App.config文件
    c#防止多次运行代码收集
    c# winform 关闭窗体时同时结束线程实现思路
    C# App.config 自定义 配置节 报错“配置系统未能初始化” 解决方法
    在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke 解决办法
    用 C# 在 Windows 7 中写注册表想到的
    this指针
    UML类图,用例图,时序图
    常见的框架模式:MVC MVP MTV等
  • 原文地址:https://www.cnblogs.com/lfri/p/11286172.html
Copyright © 2020-2023  润新知