【BZOJ 3122】 [Sdoi2013]随机数生成器 (BSGS)

3122: [Sdoi2013]随机数生成器

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 1442  Solved: 552

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<=a<=P-1,0<=b<=P-1,2<=P<=10^9

【分析】

  这题简直坑爹到家了!!p是质数不说,还有各种恶心特判!!!!

  a=0,a=1,b=0都要特判。

  虽说自己推出了通项公式,但是哪里的除法可以逆元哪里不可以都不知道,一开始通分各种wa!!

  看别人的题解吧:

已知xn=a*xn-1+b%p,求最小的n令xn=t

首先,若x1=t,则返回1

若a=0,则若b=t 返回2,否则无解

若a=1,则T=t-x1+p%p,可以列出方程

b*x+p*y==T % p

若a>=2,则根据等比数列和可得

xn=t=x1*a^(n-1)+b*(a^(n-1)-1)/(a-1) %p

由于p为质数,所以令c=inv[a-1]=(a-1)^(p-2)

x1*a^(n-1)+b*c*(a^(n-1))==b*c+t %p

(x1+b*c)*(a^(n-1))==b*c+t % p

令A=x1+b*c,B=p,C=b*c+t

则就是解A*X+B*Y==C %p

解出来X=a^(n-1),然后这个用BSGS求就可以了

http://www.cnblogs.com/qzqzgfy/p/5581955.html

我的代码:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 using namespace std;
  9 #define LL long long
 10 #define Maxn 35000
 11
 12 struct node
 13 {
 14     LL id,val;
 15 }t[Maxn];
 16
 17 LL ax,ay;
 18 LL exgcd(LL a,LL b)
 19 {
 20     if(b==0) {ax=1;ay=0;return a;}
 21     LL g=exgcd(b,a%b);
 22     LL xx=ax;
 23     ax=ay;ay=xx-(a/b)*ay;
 24     return g;
 25 }
 26
 27 bool cmp(node x,node y) {return (x.val==y.val)?(x.id<y.id):(x.val<y.val);}
 28
 29 LL cnt;
 30
 31 LL t_div(LL x)
 32 {
 33     LL l=0,r=cnt;
 34     while(l<r)
 35     {
 36         LL mid=(l+r)>>1;
 37         if(t[mid].val==x) return t[mid].id;
 38         if(t[mid].val>x) r=mid-1;
 39         else l=mid+1;
 40     }
 41     if(t[l].val==x) return t[l].id;
 42     return -1;
 43 }
 44
 45 LL get_ans(LL k,LL a,LL c,LL p)
 46 {
 47     LL sq=(LL)ceil(sqrt((double)p));
 48     t[0].id=0;t[0].val=k%p;
 49     for(LL i=1;i<=sq;i++) t[i].val=(t[i-1].val*a)%p,t[i].id=i;
 50
 51     sort(t+1,t+1+sq,cmp);
 52     cnt=0;
 53     for(LL i=1;i<=sq;i++) if(t[i].val!=t[i-1].val) t[++cnt]=t[i];
 54
 55     LL bm=1;
 56     for(LL i=1;i<=sq;i++) bm=(bm*a)%p;
 57     LL g=exgcd(bm,p);
 58     ax=(ax%(p/g)+(p/g))%(p/g);
 59     bm=ax;
 60
 61     LL tmp=c%p;
 62     for(LL i=0;i<=sq;i++)
 63     {
 64         LL now=t_div(tmp);
 65         if(now!=-1) return now+i*sq;
 66         tmp=(tmp*bm)%p;
 67     }
 68     return -1;
 69 }
 70
 71 LL ffind(LL k,LL a,LL c,LL p)
 72 {
 73     LL x=k;
 74     for(LL i=0;i<=100;i++)
 75     {
 76         if(x==c) return i;
 77         x=(x*a)%p;
 78     }
 79     LL g;
 80     x=0;
 81     while((g=exgcd(a,p))!=1)
 82     {
 83         p/=g;
 84         k=(k*(a/g))%p;
 85         if(c%g!=0) return -1;
 86         c/=g;
 87         x++;
 88     }
 89     LL ans=get_ans(k,a,c,p);
 90     if(ans==-1) return -1;
 91     return ans+x;
 92 }
 93
 94 int main()
 95 {
 96     int T,kase=0;
 97     scanf("%d",&T);
 98     while(T--)
 99     {
100         // printf("%d: ",++kase);
101         LL p,a,b,x,t,c;
102         scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x,&t);
103         // if(b==0) {printf("1\n");continue;}
104         if(t==x) {printf("1\n");continue;}
105         if(a==0&&b==t) {printf("2\n");continue;}
106         else if(a==0) {printf("-1\n");continue;}
107         if(a==1)
108         {
109             LL g=exgcd(b,p);
110             c=t-x;c=(c%p+p)%p;
111             if(c%g!=0) {printf("-1\n");continue;}
112             ax*=c/g;
113             ax=(ax%(p/g)+(p/g))%(p/g);
114             printf("%d\n",ax+1);
115             continue;
116         }
117
118         LL phi;
119         if(b%(a-1)==0) phi=b/(a-1);
120         else
121         {
122             if(exgcd(a-1,p)!=1) {printf("-1\n");continue;}
123             ax=(ax%p+p)%p;
124             phi=(b*ax)%p;
125         }
126         LL A=x+phi,B=phi+t;
127
128         if(b==0) A=x,B=t;
129
130         A=(A%p+p)%p; B=(B%p+p)%p;
131         // if(A==0) {printf("-1\n");continue;}
132
133         LL ans=ffind(A,a,B,p);
134
135         if(ans==-1) printf("-1\n");
136         else printf("%lld\n",ans+1);
137     }
138     return 0;
139 }

BZOJ 3211

2016-09-05 18:24:44

时间: 2024-08-07 05:50:13

【BZOJ 3122】 [Sdoi2013]随机数生成器 (BSGS)的相关文章

BZOJ 3122 [Sdoi2013]随机数生成器 BSGS

题意:链接 方法: BSGS 解析: 首先他给出了你数列在mod p意义下的递推式. 所以我们可以求出来通项. Xn+1+k=a?(Xn+k) 所以b=(a?1)?k 则我们可以解出来k 那么这个数列的通项是什么呢? Xn=an?1?(X1+k)?k 题中给定Xn 求出n就行了. 所以只需要移项就好了. 这里有个问题,此时我们的通项公式是不包含首项的,所以需要特判首项,另外还有第一项以外为常数项的时候. 代码: #include <cmath> #include <cstdio>

BZOJ 3122 SDOI2013 随机数生成器

一大堆边界一开始并不知道,胡乱判了几个之后一直WA 无奈之下只好去下载了数据,然后就疯狂判各种奇怪的边界了 刨去边界问题 首先我们考虑a=1的情况 x1+k*b=t(mod p) ex_gcd即可解 考虑a>1的情况 令S=X+b/(a-1) 原式就变成了一个等比数列 即S1*a^k=(t+b/(a-1))(mod p) 移项之后BSGS解即可 其他边界都可以O(1)判断 #include<cstdio> #include<cstring> #include<iostr

BZOJ 3122 SDOI2013 随机数生成器 数论 EXBSGS

题目大意:给定一个数列X(i+1)=(a*Xi+b)%p 求最小的i>0,使Xi=t 0.0 此题能1A真是太好了 首先讨论特殊情况 若X1=t ans=1 若a=0 ans=b==t?2:-1 若a=1 X1+b*(ans-1)==t (%p) 扩展欧几里得 令 temp=b/(a-1) 则有 (X(i+1)+temp)=a*(Xi+temp) Xans=(X1+temp)*a^(ans-1)-temp 其中Xans%p=t 则有 (X1+temp)*a^(ans-1)-temp == t (

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

3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1362  Solved: 531[Submit][Status][Discuss] Description Input 输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数. 接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据.保证X1和t都是合法的页码. 注意:P一定为质数 Output 共T行,每行一个整数表示他最早读到第t页是

bzoj3122: [Sdoi2013]随机数生成器

3122: [Sdoi2013]随机数生成器 Description Input Output HINT $ 0 \leqslant a \leqslant P-1,0 \leqslant b \leqslant P-1,2 \leqslant P \leqslant 10^9 $ BSGS裸题 把线性递推式转化为通项公式为 $ x[n] = x1 * A^{n-1} + \frac {B*A^{n-1}} {A-1} = t $ 移项,得: $ (x1 + \frac {B} {A-1}) *

【bzoj3122】: [Sdoi2013]随机数生成器 数论-BSGS

[bzoj3122]: [Sdoi2013]随机数生成器 当a>=2 化简得 然后 BSGS 求解 其他的特判 : 当 x=t  n=1 当 a=1  当 a=0 判断b==t 1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <map&

BZOJ 2875: [Noi2012]随机数生成器( 矩阵快速幂 )

矩阵快速幂...+快速乘就OK了 -------------------------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; typedef long long ll; ll MOD, a, c, x, n, g; ll MUL(ll a, ll b) { ll ans = 0; for(; b; b >>= 1

[Sdoi2013]随机数生成器(BSGS)

#include<map> #include<cmath> #include<cstdio> #include<iostream> #define ll long long using namespace std; inline int read(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'

[bzoj 2875][noi2012]随机数生成器

传送门 Description 栋栋最近迷上了随机算法,而随机数是生成随机算法的基础.栋栋准备使用线性同余法(Linear Congruential Me thod)来生成一个随机数列,这种方法需要设置四个非负整数参数m,a,c,X[0],按照下面的公式生成出一系列随机 数X[n]X[n+1]=(aX[n]+c)mod m其中mod m表示前面的数除以m的余数.从这个式子可以看出,这个序列的下一个数 总是由上一个数生成的.用这种方法生成的序列具有随机序列的性质,因此这种方法被广泛地使用,包括常用