Processing math: 100%

【bzoj3122】 Sdoi2013—随机数生成器

http://www.lydsy.com/JudgeOnline/problem.php?id=3122 (题目链接)

题意

  对于一个数列${X_i}$,其递推式为:${X_{i+1}=(a*X_i+n)~mod~P}$,求最小的${i}$满足${X_i=t}$。

Solution

  大家还记得数学中数列那一章吗,那么推倒这个数列的方法一定是老师重点强调过的:

$${X_{i+1}+λ=a*(X_i+λ)}$$

$${可以算出λ=\frac{b}{a-1}}$$

$${令B_i=X_i+\frac{b}{a-1}}$$

$${则B_{i+1}=a*B_i,为等比数列}$$

$${B_i=B_1*a^{i-1}}$$

$${B_i=(X_1+\frac{b}{a-1})*a^{i-1}}$$

$${\because B_i=X_i+\frac{b}{a-1}}$$

$${\therefore X_i=(X_1+\frac{b}{a-1})*a^{i-1}-\frac{b}{a-1}}$$

$${令c=(a-1)^{-1}~(mod~p)}$$

$${则X_i=(X_1+b*c)*a^{i-1}+b*c~~(mod~p)}$$

$${即求(X_1+b*c)*a^{i-1}≡t-b*c~~(mod~p)}$$

  因为a的取值,我们需要考虑特殊情况并进行分类讨论。

  首先要特判${X_1=t}$的情况,因为这个在后面不好处理,不如讨论之前就直接排除在外。

  1.${a=0}$

  这种情况下要么是${t=X_1}$,要么是${t=X_2}$,因为${X_n=b~(n>1)}$

  2.${a=1}$

  那么数列就可以简化为:${X_{i+1}=X_i+b}$,是一个等差数列。

  即求:${X_1+b*(i-1)=t~(mod~p)}$

  这可以用exgcd求解。

  3.${a>=2}$

  那么就是我们上面推下来的式子,先用exgcd求出${a^{i-1}}$的最小正整数解,然后用BSGS计算${i-1}$的取值。

细节

  数学题就是细节多,exgcd判无解。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// bzoj3122
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
 
map<LL,LL> mp;
 
LL power(LL a,LL b,LL c) {
    LL res=1;
    while (b) {
        if (b&1) res=res*a%c;
        b>>=1;a=a*a%c;
    }
    return res;
}
LL BSGS(LL a,LL b,LL p) {
    LL m=ceil(sqrt(p));
    LL inv=power(a,p-1-m,p),e=1;
    mp.clear();mp[1]=0;
    for (int i=1;i<m;i++) {
        e=e*a%p;
        if (!mp.count(e)) mp[e]=i;
    }
    for (int i=0;i<m;i++) {
        if (mp.count(b)) return mp[b]+i*m+1;
        b=b*inv%p;
    }
    return -1;
}
void exgcd(LL a,LL b,LL &d,LL &x,LL &y) {
    if (b==0) {d=a;x=1;y=0;return;}
    exgcd(b,a%b,d,y,x);
    y-=a/b*x;
}
int main() {
    LL P,A,B,X1,t;
    int T;scanf("%d",&T);
    while (T--) {
        scanf("%lld%lld%lld%lld%lld",&P,&A,&B,&X1,&t);     
        if (X1==t) {puts("1");continue;}   //一定要特判,如果进入BSGS后b为0出来的解是-1
        if (A==0) {
            if (B==t) puts("2");
            else puts("-1");
        }
        if (A==1) {
            LL x,d,y;
            t=(t-X1)%P;if (!t) {puts("1");continue;}
            exgcd(B,P,d,x,y);
            if (t%d!=0) {puts("-1");continue;}
            printf("%lld\n",((t/d)*x%(P/d)+(P/d))%(P/d)+1);
        }
        if (A>=2) {
            LL x,d,y;
            LL c=power(A-1,P-2,P);
            t=(t+B*c)%P;
            exgcd(X1+B*c,P,d,x,y);
            if (t%d!=0) {puts("-1");continue;}
            x=((t/d)*x%(P/d)+(P/d))%(P/d);
            printf("%lld\n",BSGS(A,x,P));
        }
    }
    return 0;
}

  

posted @   MashiroSky  阅读(260)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示