• 2019牛客多校第五场C generator 2 hash,bsgs模板


    generator 2

    题意

    给出(x_0,a,b,p),有方程(x_iequiv (a*x_{i-1}+b)(\% p)),求最小的i,使得(x_i=v),不存在输出-1

    分析

    经过公式运算可以知道,当a!=1时,由等比数列求和我们可以知道,(v=x_n=x_0*a^n+b*frac{a^n-1}{a-1}),化简得(a^nequiv frac{(a-1)v+b}{(a-1)x0+b} (\% p)) 这样就转化成了bsgs的形式,直接套用bsgs即可。这里需要注意的是,因为由q次询问,bsgs需要预处理没有询问参数v的一端,然后再在询问询问里面查找另外一段,这里考察的是活用bsgs,因为这和平常的bsgs是相反的,其次需要知道的是,使用unordered_map可以卡过去,但是稳一点还是手写hash
    注意要特判左边算出来是1的情况
    a=0和a=1也需要特判

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+3;
    namespace Hash{
        const int maxn=1e6+3;
        int cnt,head[maxn],nxt[maxn];
        ll val[maxn],pos[maxn];
        void init(){
            cnt=0;
            memset(head,-1,sizeof(head));
        }
        void insert(ll x,ll y){
            ll tx=x%maxn;
            val[cnt]=x,pos[cnt]=y;
            nxt[cnt]=head[tx];
            head[tx]=cnt++;
        }
        ll get(ll x){
            ll tx=x%maxn;
            for(int i=head[tx];~i;i=nxt[i]){
                if(val[i]==x) return pos[i]; 
            }
            return -1;
        }
    }
    unordered_map<ll,ll>mp;
    long long n,x0,a,b,p;
    ll mul(ll a,ll b){return 1ll*a%p*b%p;}
    ll fpow(ll a,ll b){
        ll ans=1;
        while(b){
            if(b&1)ans=mul(ans,a);
            a=mul(a,a);
            b>>=1;
            //cout<<ans<<endl;
        }
    return ans;
    }
    ll inv(ll x){
        return fpow(x,p-2);
    }
    ll add(ll a,ll b){return (a%p+b%p+p)%p;}
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            ll q,v;
            //mp.clear();
    Hash::init();
            scanf("%lld%lld%lld%lld%lld",&n,&x0,&a,&b,&p);
            scanf("%lld",&q);
            ll m=sqrt(p)+1;
            ll t=fpow(a,m);
      ll  s=1;
            for(int i=1;i<=m;i++){
              /*  if(!mp.count(s)){
                    mp[s]=i*m;
                }*/
                s=1ll*s*t%p;
            ll tp=Hash::get(s);
                if(tp==-1) Hash::insert(s,i*m);
            }
            while(q--){
                scanf("%lld",&v);
             //   mp.clear();
                if(a==0){
                    if(x0==v)printf("0
    ");
                    else if(v==b)printf("1
    ");
                    else printf("-1
    ");
                continue;
                }
                if(a==1){
                    ll ans=((v-x0+p)%p)*inv(b)%p;
                    if(ans<n)printf("%lld
    ",ans);
                    else printf("-1
    ");
                    continue;
                }
            ll y=mul(add(b,mul(v,a-1)),inv(((mul(a,x0)-x0+p)%p+b)%p));
            //cout<<"y "<<y<<endl;
            ll ans=p+1;
            ll  s=y;
            if(y==1){
                printf("0
    ");
                continue;
            }
            for(int i=0;i<m;i++){
             /*   if(mp.count(s)){
                    ans=min(ans,mp[s]-i);
                }*/
            ll tp=Hash::get(s);
                    if(tp!=-1) ans=min(ans,tp-i);
                s=s*a%p;
            }
            if(ans>p||ans>=n)printf("-1
    ");
            else printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Kruskal重构树学习笔记
    亚洲和欧洲的分界线是谁划分的?
    代码目录 (App_Code 目录)及namespace的理解
    Events解惑——来自MSDN
    HttpContext.Current.Response和Response有什么区别?
    Ramdisk 内存盘的使用
    MVC模式 介绍
    关于Windows Workflow Foundation 调试时的经验小解(不断添加)
    关于类成员变量的声明和实例化的时机
    软件名称备份
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/11406593.html
Copyright © 2020-2023  润新知