bzoj 3122

本文详细解析了BZOJ3122 [SDOI2013]随机数生成器问题的解法,包括特殊情况的处理、使用exgcd求解线性方程组最小解的方法,以及如何通过优化避免溢出等问题。

「BZOJ3122」[SDOI2013]随机数生成器(from hzwer.com)

2015年5月2日 4,319 6

描述

输入

输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数。

接下来Ť行,每行有五个整数P,A,B,X1,T,表示一组数据。保证X1和吨都是合法的页码。

注意:P一定为质数

输出

共Ť行,每行一个整数表示他最早读到第吨页是哪一天。如果他永远不会读到第吨页,输出-1。

题解

注意特判a = 1的情况,用exgcd求线性方程组最小解

多用longlong防止乘爆

把式子推清楚再写题

点击打开链接



的#include <cstdio>的
的#include <:字符串>
的#include <iostream的>
的#include <算法>
的#include <地图>
的#include <CMATH>
使用namespace std;
#define maxn 100020

typedef long long ll;
int T,a,b,p,x1,t,ans;
map <int,int> \ tmp;

inline ll power(ll x,int y){
	ll res = 1;
	while(y){
		如果(y&1)res = res * x%p;
		y >> = 1;
		x = x * x%p;
	}
	返回资源;
}
int gcd(int x,int y){
	如果(!y)返回x;
	return gcd(y,x%y);
}
void exgcd(int a,int b,int&x,int&y){
	if(!b){
		x = 1,y = 0;
		返回;
	}
	exgcd(b,a%b,x,y);
	int t = x;
	x = y,y = t  - (a / b)* y;
}
void solve(){
	if(x1 == t){printf(“1 \ n”); 返回; }
		如果(a == 1){
			int d = gcd(b,p),c =(t-x1 + p)%p,x = 0,y = 0;
			if(c%d){printf(“ -  1 \ n”); 返回; }
			exgcd(B,P,X,Y);
		// x =(x%p + p)%p;
		// x =(ll)x *(c / d)%p;
		// while(x> =(ll)(p / d)*(c / d)%p)x  -  =(ll)(p / d)*(c / d)%p;
			x =(11)x *(c / d)%p;
			if(x <0)x + = p;
			printf(“%d \ n”,x + 1);
			返回;
		}
		如果(a == 0){
			if(b == t)printf(“2 \ n”); 
			else printf(“ -  1 \ n”);
			返回;
		}
		inva = power(a,p-2); inv = power(((ll)(a-1)* x1 + b)%p,p  -  2)int sz =(int)sqrt(p)+ 1;
		ll x =((ll)t *(a-1)%p + b)* inv%p; 
		mp [(int)x] = 1;
		for(int i = 1; i <= sz; i ++){
			x = x * inva%p;
			if(!mp [(int)x])mp [(int)x] = i + 1;	
		}
		if(mp [1]){printf(“%d \ n”,mp [1]); 返回; }
		x = 1; a = power(a,sz);
		for(int i = 1; i <= p / sz + 1; i ++){
			x =(ll)x * a%p;
			if(mp [(int)x]){printf(“%d \ n”,mp [(int)x] + i * sz); 返回; }
		}
		的printf( “ -  1 \ n”);
}
int main(){
	freopen函数( “input.txt中”, “R”,标准输入);
	的scanf( “%d”,&T);
	而(T--){
		mp.clear();
		scanf(“%d%d%d%d%d”,&p,&a,&b,&x1,&t);
		解决(); //多组数据写成函数
	}
	返回0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值