[JZOJ3211] [SDOI2013] Random Number Generator

╰( ̄▽ ̄)╭

Xiao W likes reading, especially John Christophe. Recently, Xiao W is going to read a new book. This book has a total of P pages. The number of pages is 0.p-1.
Xiao W is very busy, so he can only read one page a day. To make things more interesting, he plans to use the linear congruence method he learned in NOI 2012 to generate a sequence to decide which page to read each day.
We use Xi to indicate the number of pages generated by this method, that is, which page will be read on the first day of Little W. This method needs to set three parameters a, b, X1 to satisfy 0 < a, b, X1 < p-1, and a, b, X1 are all integers. According to the following formula, a series of integers are generated according to the following formula.
Xi+1=(aXi+b)modp
Where mod p denotes the remainder of the previous number divided by P.
It can be found that the next number in this sequence is always generated from the previous number, and each item is within the range of 0..p -1, which is a legal page number. At the same time, it should be noted that this method may lead to the same page number read in one or two days.
Xiao W is eager to read page t of this book. So he wants to know, for a given set of a, b, X1, if the linear congruence method is used to generate the page numbers read every day, which day is the earliest page to read, or to point out that he will never read page t.
p<=109

(⊙ ▽ ⊙)

It is easy to find the general formula of x.
Let c=ba_1,
be

xn=an−1(x1+c)−c

Handling of special cases:
Before that, we must guarantee a!=1;
So we use the extended Euclidean method to solve the case of a=1. (1)
At the same time, we have to make sure that a!=0, because when a=0 and n=1, 00 is meaningless.
So for the case of a=0, the solution is directly special judgement. II.

At this time, the title requires: xn_t(mod p), equivalent to: an_1 (x1 + c)c_t(mod p).
Transfer terms available: an_1_t+cx1+c(mod p)

Handling of special cases:
Before that, we have to make sure that x1 and b are not zero at the same time, otherwise the denominator x1+c will be zero.
So for the case where x1 and b are both zero, the solution is specially determined. 3.

Let ans=n_1, S=t+cx1+c, and the final problem is transformed into a solution

aans≡S(mod p)

The minimum positive integer solution. (About ans)

So you can do it. BSGS algorithm Now.

( ̄~ ̄)

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
#define ll long long
using namespace std;
const char* fin="jzoj3211.in";
const char* fout="jzoj3211.out";
const ll inf=0x7fffffff;
const ll maxh=1000007;
ll t,i,j,k,A,B,X1,n,mo;
ll h[maxh],minx[maxh];
bool noans;
ll hash(ll v){
    ll k=v%maxh;
    while (h[k] && h[k]!=v) k=(k+1)%maxh;
    return k;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
    if (b==0){
        x=1;
        y=0;
        return a;
    }
    ll r=exgcd(b,a%b,x,y);
    ll t=x;
    x=y;
    y=t-a/b*y;
    return r;
}
ll qpower(ll a,ll b){
    ll c=1;
    while (b){
        if (b&1) c=c*a%mo;
        a=a*a%mo;
        b>>=1;
    }
    return c;
}
int main(){
    freopen(fin,"r",stdin);
    freopen(fout,"w",stdout);
    scanf("%lld",&t);
    while (t--){
        scanf("%lld%lld%lld%lld%lld",&mo,&A,&B,&X1,&n);
        if (A==0){
            if (X1==n) printf("1\n");
            else if (B==n) printf("2\n");
            else printf("-1\n");
        }else if (A==1){
            ll x,y;
            k=exgcd(mo,B,x,y);
            if ((n-X1)%k) printf("-1\n");
            else{
                x*=(n-X1)/k;
                y*=(n-X1)/k;
                y=(y%(mo/k)+(mo/k))%(mo/k);
                printf("%lld\n",y+1);
            }
        }else if (B==0 && X1==0){
            if (X1==n) printf("1\n");
            else printf("-1\n");
        }else{
            ll ks=(ll)sqrt(mo),tmp=qpower(A,ks),tmd=qpower(tmp,mo-2);
            memset(h,0,sizeof(h));
            memset(minx,0,sizeof(minx));
            j=1;
            for (i=0;i<ks;i++){
                k=hash(j);
                h[k]=j;
                if (!minx[k] || minx[k]>i) minx[k]=i;
                j=j*A%mo;
            }
            ll C=B*qpower(A-1,mo-2)%mo;
            j=(n+C)*qpower(X1+C,mo-2)%mo;
            noans=true;
            for (i=0;i<=ks;i++){
                k=hash(j);
                if (h[k]){
                    ll ans=minx[k]+i*ks+1;
                    printf("%lld\n",ans);
                    noans=false;
                    break;
                }
                j=j*tmd%mo;
            }
            if (noans) printf("-1\n");
        }
    }
    return 0;
}

(⊙v⊙)

For a recursive problem, we can consider first finding the general term formula and factorizing it.

Posted by jd307 on Mon, 25 Mar 2019 21:00:28 -0700