bzoj3122【SDOI2013】随机数生成器

3122: [Sdoi2013]随机数生成器

Time Limit: 10 Sec  Memory Limit: 256 MB

Submit: 1204  Solved: 471

[Submit][Status][Discuss]

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

扩展欧几里得求逆元+BSGS

题解戳这里:http://hzwer.com/6963.html

(公式恐惧症飘过,不带走一片云彩)

注意各种特殊情况的判断,WA了很多次...

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
using namespace std;
ll T,p,a,b,x1,t;
map<ll,int> mp;
inline int read()
{
	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 x*f;
}
inline ll getpow(ll x,ll y,ll p)
{
	ll ret=1;
	for(;y;y>>=1,x=x*x%p) if (y&1) ret=ret*x%p;
	return ret;
}
inline ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if (!b){x=1;y=0;return a;}
	ll ret=exgcd(b,a%b,x,y);
	ll t=x;x=y;y=t-a/b*y;
	return ret;
}
inline ll bsgs(ll a,ll b,ll p)
{
	if (b==1) return p-1;
	ll m=ceil(sqrt(p));
	mp.clear();
	ll tmp=1,inv=getpow(a,p-2,p);
	F(i,0,m)
	{
		ll h=b*tmp%p;
		if (!mp[h]) mp[h]=i;
		tmp=tmp*inv%p;
	}
	tmp=1;
	ll base=getpow(a,m,p);
	F(i,0,m)
	{
		if (mp[tmp])
		{
			ll ret=i*m+mp[tmp];
			return ret;
		}
		tmp=tmp*base%p;
	}
	return -1;
}
inline ll calc1()
{
	ll c=((t-x1)%p+p)%p,x,y;
	ll tmp=exgcd(b,p,x,y);
	if (c%tmp) return -1;
	return (x*c/tmp%p+p)%p+1;
}
inline ll calc2()
{
	ll c=getpow(a-1,p-2,p);
	ll t1=(b*c%p+x1)%p,t2=(b*c%p+t)%p,x,y;
	if (t1==0)
	{
		if (t2==0) return 1;
		else return -1;
	}
	if (t2==0) return -1;
	ll tmp=exgcd(t1,p,x,y);
	if (t2%tmp) return 0;
	t2/=tmp;x=(x%p+p)%p;
	ll t=bsgs(a,x*t2%p,p);
	if (t==-1) return -1;
	else return t+1;
}
inline ll getans()
{
	if (x1==t) return 1;
	if (a==0) return b==t?2:-1;
	if (a==1) return calc1();
	return calc2();
}
int main()
{
	int T=read();
	while (T--)
	{
		p=read();a=read();b=read();x1=read();t=read();
		printf("%lld\n",getans());
	}
}
时间: 2024-12-29 04:26:57

bzoj3122【SDOI2013】随机数生成器的相关文章

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-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页是

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

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

[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 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]随机数生成器 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 随机数生成器 数论 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 (

SDOI2013 随机数生成器

题目链接:戳我 就是大力推式子,然后上BSGS就行了. \[x_n\equiv a^{n-1}x_1+b(a^{n-2}+a^{n-3}+...+a)\pmod p\] \[t\equiv a^{n-1}x_1+b\sum_{i=0}^{n-2}a^i\pmod p\] \[t\equiv a^{n-1}x_1+b\times \frac{1\times(1-a^{n-1})}{1-a}\pmod p\] \[t\equiv a^{n-1}x_1+\frac{b}{1-a}-\frac{b}{1

P3306 [SDOI2013]随机数生成器

思路:\(BSGS\) 提交:\(1\)次 题解: 原式可以化为\[x_{i+1}+\frac{b}{a-1}=a(x_{i}+\frac{b}{a-1})\mod p\] 这不是等比数列吗? \[x_{n}+\frac{b}{a-1}=a^{n-1}\cdot (x_{1}+\frac{b}{a-1})\mod p\] 所以有 \[a^{n-1}=(x_{1}+\frac{b}{a-1})^{-1}\cdot (x_{n}+\frac{b}{a-1})\mod p\] 这样我们可以\(BSGS