【bzoj3122】【SDOI2013】 随机数生成器

本文介绍了一种利用秦九昭算法和等比数列求和的方法来解决模意义下的序列求解问题,并通过BSGS算法高效求解离散对数问题。文中详细解释了求逆元的过程及其实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

公式其实挺容易推的,看见zyf推的好复杂= =,其实直接代秦九昭算法,然后用等比数列求和就能推出来,推到最后应该是
Xn+b/a−1≡an−1(X1+b/a−1)(modp)
然后会发现除了a^n-1其他都是常数,注意要求逆元
然后直接BSGS就好了,求逆元可以用exgcd也可以用a^(p-2)求.
代码找不到了/(ㄒoㄒ)/~~,我贴zyf神犇的好了毕竟模板都是照着她写的.

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
#define LL long long

LL T,P,a,b,x1,t;
LL ny1,ny2,val1,val2,val3;
LL ans;
map <LL,LL> hash;

inline LL fast_pow(LL a,LL p){
    LL ans=1;
    for (;p;p>>=1,a=a*a%P)
      if (p&1)
        ans=ans*a%P;
    return ans;
}

inline LL BSGS(LL a,LL b){
    LL m=ceil(sqrt(P));
    LL a_m=fast_pow(a,m);
    hash.clear();

    LL mul=1;
    LL val=mul*b%P;
    hash[val]=0;
    for (LL j=1;j<=m;++j){
        mul=mul*a%P;
        val=mul*b%P;
        hash[val]=j;
    }

    mul=1;
    for (LL i=1;i<=m;++i){
        mul=mul*a_m%P;
        if (hash[mul]){
            LL x=i*m-hash[mul];
            return x+1;
        }
    }
    return -1;
}

int main(){
    scanf("%lld",&T);
    while (T--){
        scanf("%lld%lld%lld%lld%lld",&P,&a,&b,&x1,&t);

        //一坨特判
        if (t==x1){
            printf("1\n");
            continue;
        }
        if (a==0){
            if (t==b) printf("2\n");
            else printf("-1\n");
            continue;
        }
        if (a==1&&b==0){
            printf("-1\n");
            continue;
        }
        if (a==1){
            int nyb=fast_pow(b,P-2);
            ans=((((t-x1)%P+P)%P)*nyb%P)%P;
            printf("%lld\n",ans+1);
            continue;
        }


        ny1=fast_pow(a-1,P-2);
        val1=b*ny1%P;

        val2=(x1%P+val1)%P;
        ny2=fast_pow(val2,P-2);

        val3=(t+val1)%P;
        b=(val3*ny2)%P;

        ans=BSGS(a,b);
        printf("%lld\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值