码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3122【SDOI2013】随机数生成器

时间:2016-04-13 02:16:49      阅读:280      评论:0      收藏:0      [点我收藏+]

标签:

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());
	}
}


bzoj3122【SDOI2013】随机数生成器

标签:

原文地址:http://blog.csdn.net/aarongzk/article/details/51138647

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!