题解 P3306 【[SDOI2013]随机数生成器】

题目链接

Solution [SDOI2013]随机数生成器

题目大意:定义\(X_i = aX_{i-1}+b\),给定\(X_1\),求最小的\(n\)使得\(X_n \equiv t(mod \; p)\)

分析:大力化简柿子

\[X_1=X_1\]

\[X_2 = aX_1+b\]

\[X_3=a^2X_1+ab + b\]

\[X_4 = a^3X_1+a^2b+ab+b\]

观察得出\(X_n=a^{n-1}X_1+b\sum_{i=0}^{n-2}a^i\)

发现后面是一个等比数列求和

\(S=\sum_{i=0}^{n-2}a^i\)

\(\therefore aS=\sum_{i=1}^{n-1}a^i\)

\(\therefore (a-1)S=a^{n-1}-1\)

\(\therefore S= \sum_{i=0}^{n-2}=a^{n-1}-1\)

继续化简:

\(X_n=a^{n-1}X_1+b \cdot \frac{a^{n-1}-1}{a-1}\)

\(X_n=a^{n-1}X_1+a^{n-1} \cdot \frac{b}{a-1} - \frac{b}{a-1}\)

\(X_n=a^{n-1}(X_1+\frac{b}{a-1})-\frac{b}{a-1}\)

\(X_n=a^{n-1}(X_1+\frac{b}{a-1})-\frac{b}{a-1} \equiv t(mod \; p)\)

\(\therefore a^{n-1}(X_1+\frac{b}{a-1}) \equiv t + \frac{b}{a-1}\)

\(\therefore a^{n-1} \equiv \frac{t+\frac{b}{a-1}}{X_1+\frac{b}{a-1}}\)

直接\(BSGS\)求解即可,模意义下用费马小定理求一下逆元

然后有一些毒瘤的细节

  • \(Detail\;1\)\(X_1=t\)\(ans=1\)
  • \(Detail\;2\)\(a=0\)时,\(X_1=X_1,X_n \equiv b(n \neq 2)\)
  • \(Detail\;3\)\(a=1\)时,\(X_n=X_1+b(n-1)\),有\(X_1+b(n-1) \equiv t(mod\;p)\),\(n=\frac{t-X_1}{b}+1\),这里用裴蜀定理判断一下有没有解
#include <cstdio>
#include <cmath>
#include <unordered_map>
using namespace std;
typedef long long ll;
ll p,a,b,X0,t,T;
namespace BSGS{
    unordered_map<ll,int> mp;
    inline ll qpow(ll a,ll b,ll mod){
        ll res = 1,base = a;
        while(b){
            if(b & 1)res = res * base % mod;
            base = base * base % mod;
            b >>= 1;
        }
        return res;
    }
    inline ll gcd(ll a,ll b){
        return !b ? a : gcd(b,a % b);
    }
    inline ll inv(ll x,ll p){
        return qpow(x,p - 2,p);
    }
    inline ll bsgs(ll y,ll z,ll p){
        ll m = sqrt(p) + 1;mp.clear();
        y %= p,z %= p;
        if(y % p == 0 && z)return -1;
        for(ll t = z,i = 0;i < m;i++,t = t * y % p)mp[t] = i;
        for(ll w = qpow(y,m,p),t = w,i = 1;i <= m + 1;i++,t = t * w % p)
            if(mp.find(t) != mp.end())return i * m - mp[t];
        return -1;
    }
}using namespace BSGS;
inline void solve(){
    scanf("%lld %lld %lld %lld %lld",&p,&a,&b,&X0,&t);
    if(X0 == t){
        printf("%d\n",1);
        return;
    }
    if(a == 0){
        if(b == t)printf("2\n");
        else printf("-1\n");
        return;
    }
    if(a == 1){
        ll d = gcd(b,p);
        if((t - X0) % d)printf("-1\n");
        else printf("%lld\n",1ll * (((t - X0) % p) + p) % p * inv(b % p,p) % p + 1);
        return;
    }
    ll z = t + b * inv(a - 1,p);z %= p;
    z *= inv((X0 + (b * inv(a - 1,p)) % p) % p,p);z %= p;
    ll ans = bsgs(a,z,p);
    if(ans == -1)printf("-1\n");
    else printf("%lld\n",ans + 1);
}
int main(){
    scanf("%lld",&T);
    while(T--)solve();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/colazcy/p/11652731.html