[SDOI2013]随机数生成器

Description

Input
输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数。
接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据。保证X1和t都是合法的页码。
注意:P一定为质数

Output
共T行,每行一个整数表示他最早读到第t页是哪一天。如果他永远不会读到第t页,输出-1。

Sample Input
3
7 1 1 3 3
7 2 2 2 0
7 2 2 2 1

Sample Output
1
3
-1

HINT
\(0\leqslant a\leqslant P-1,0\leqslant b\leqslant P-1,2\leqslant P\leqslant10^9\)


我们推推式子可以发现
\[ X_n=a^{n-1}X_1+\sum\limits_{i=0}^{n-2}a^ib \]
然后后面那玩意显然是等比数列,然后我们就可以得到
\[ \begin{align}X_n&=a^{n-1}X_1+\dfrac{b(1-a^{n-1})}{1-a}\nonumber\\&=a^{n-1}X_1+\dfrac{b}{1-a}-\dfrac{ba^{n-1}}{1-a}\nonumber\\&=a^{n-1}(X_1-\dfrac{b}{1-a})+\dfrac{b}{1-a}\nonumber\\\Longrightarrow\dfrac{X_nb}{1-a}&=a^{n-1}(X_1-\dfrac{b}{1-a})\nonumber\end{align} \]
然后直接用扩展BSGS就好了

/*program from Wolfycz*/
#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
#define Fi first
#define Se second
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>inline T frd(T x){
    int f=1; char ch=gc();
    for (;ch<'0'||ch>'9';ch=gc())   if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
template<typename T>inline T read(T x){
    int f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x<0)    putchar('-'),x=-x;
    if (x>9)    print(x/10);
    putchar(x%10+'0');
}
map<int,int>Mp;
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int mlt(int a,int b,int p){
    int res=1;
    for (;b;b>>=1,a=1ll*a*a%p)  if (b&1)    res=1ll*res*a%p;
    return res;
}
int BSGS(int a,ll c,int p){
    Mp.clear();
    if (a==c)   return 1;
    int lmt=(int)sqrt(p);
    for (int i=0;i<lmt;i++){
        int res=1ll*c*mlt(a,i,p)%p;
        map<int,int>::iterator it=Mp.find(res);
        if (it==Mp.end())   it=Mp.insert(map<int,int>::value_type(res,i)).Fi;
        it->Se=i;
    }
    for (int i=1;i*lmt<p;i++){
        int res=mlt(a,i*lmt,p);
        map<int,int>::iterator it=Mp.find(res);
        if (it!=Mp.end())   return i*lmt-it->Se;
    }
    return -1;
}
int main(){
    for (int Data=read(0);Data;Data--){
        int p=read(0),a=read(0),b=read(0),k=read(0),t=read(0);
        if (k==t){
            printf("1\n");
            continue;
        }
        if (!a){
            printf(b==t?"2\n":"-1\n");
            continue;
        }
        if (a==1){
            int Ans=1ll*(t-k)*mlt(b,p-2,p)%p;
            printf(!b?"-1\n":"%d\n",(Ans+p)%p+1);
            continue;
        }
        ll x=t-1ll*a*t-b,y=k-1ll*a*k-b;
        if ((x<0&&y>0)||(x>0&&y<0)){
            printf("-1\n");
            continue;
        }
        x=abs(x)%p,y=abs(y)%p;
        int c=1ll*x*mlt(y,p-2,p)%p;
        int Ans=BSGS(a,c,p);
        printf(!~Ans?"-1\n":"%d\n",Ans+1);
    }
    return 0;
}
posted @ 2019-03-30 21:58 Wolfycz 阅读(...) 评论(...) 编辑 收藏