# 【BZOJ-3122】随机数生成器 BSGS

## 3122: [Sdoi2013]随机数生成器

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 1362  Solved: 531
[Submit][Status][Discuss]

3
7 1 1 3 3
7 2 2 2 0
7 2 2 2 1

1
3
-1

## HINT

0<=a<=P-1,0<=b<=P-1,2<=P<=10^9

## Solution

$X_{i+1}\equiv aX_{i}+b (mod p)$

==>$X_{i+1}+\frac{b}{a-1}\equiv aX_{i}+b+\frac{b}{a-1} (mod p)$
==>$X_{i+1}+\frac{b}{a-1}\equiv a(X_{i}+\frac{b}{a-1}) (mod p)$

$X_{n}+\frac{b}{a-1}\equiv a^{n-1}(X_{1}+\frac{b}{a-1}) (mod p)$

1° $X_{1}=t$ 显然ans=1

2° $a==0$ 显然得到$X_{n}\equiv b(mod p)$ 那么$b=t$时 ans=2 否则 ans=-1

3° $a==1$ 显然得到$X_{n}\equiv X_{1}+(n-1)b(mod p)$ 这样显然可以用ExGCD求解

## Code

(感觉这是这道题最短的代码了2333）

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return (long long)x*f;
}
int T;
long long p;
long long Quick_Pow(long long x,long long y,long long p)
{
long long re=1;
for (int i=y; i; i>>=1,x=x*x%p)
if (i&1) re=re*x%p;
return re;
}
long long BSGS(long long a,long long b,long long p)
{
long long m=ceil(sqrt(p)),t=1;
map<long long,long long>hash;
for (int i=0; i<=m; i++,b=b*a%p) hash[b]=i;
long long f=Quick_Pow(a,m,p);
for (long long i=1; i<=m; i++)
if (t=t*f%p,hash.count(t)) return i*m-hash[t]+1;
return -1;
}
int main()
{
while (T--)
{
long long a,b,X1,t;
if (X1==t) {puts("1"); continue;}
if (a==0) {if (t==b) puts("2"); else puts("-1"); continue;}
if (a==1) {if (!b) puts("-1"); else printf("%lld\n",((((t-X1+p)%p)*Quick_Pow(b,p-2,p)%p)%p)+1); continue;}
long long aa=Quick_Pow(a-1,p-2,p),t1=b*aa%p,t2=(X1%p+t1)%p,tt=Quick_Pow(t2,p-2,p),t3=(t+t1)%p;
printf("%lld\n",BSGS(a,t3*tt%p,p));
}
return 0;
}

——It's a lonely path. Don't make it any lonelier than it has to be.
posted @ 2016-07-30 21:06  DaD3zZ  阅读(211)  评论(0编辑  收藏  举报