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

输入
输入含有多组数据,第一行一个正整数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;
}

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

被折叠的 条评论
为什么被折叠?



