题解 LuoguP3306 [SDOI2013] 随机数生成器
题目链接:【LuoguP3306】。
前置知识
OI-Wiki:快速幂,扩展欧几里得算法(exgcd),Baby Step, Giant Step 算法。
题意
很清楚,不说。
当 时
答案很明显为
当 时
当 时
观察一下规律:
规律十分显著:
可以直接特判。
当 时
观察一下规律:
规律十分显著:
然后就是用扩展欧几里得解同余方程了。
当 时
观察一下规律:
规律十分显著:
很明显是一个等比数列。
等比数列如何求解?
首先设
。
然后求逆元之后利用 BSGS 算法求解同余高次方程。
最后可以发现其实推完公式之后就是 「SDOI2011」计算器。
代码
//the code is from chenjh
#include<cstdio>
#include<cmath>
#include<unordered_map>
typedef long long LL;
LL qpow(LL a,int b,const int p){//快速幂。
int ret=1;
for(;b;b>>=1,a=a*a%p)if(b&1)ret=ret*a%p;
return ret%p;
}
int exgcd(const int a,const int b,int&x,int&y){//扩展欧几里得。
if(!b) return x=1,y=0,a;
int d=exgcd(b,a%b,x,y);
int z=x;x=y,y=z-y*(a/b);
return d;
}
LL BSGS(int a,LL b,int p){//大步小步算法。
std::unordered_map<LL,LL> h;h.clear();//std::unordered_map 基于哈希,理论上更快,实际上也比红黑树实现的 std::map 快。
b%=p;
int t=(LL)sqrt(p)+1;
for(int j=0;j<t;j++) h[b*qpow(a,j,p)%p]=j;
a=qpow(a,t,p);
if(!a) return b?-1:1;
for(int i=0;i<=t;i++){
int v=qpow(a,i,p);
LL j=h.find(v)==h.end()?-1:h[v];
if(j>=0 && (LL)i*t-j>=0) return (LL)i*t-j;
}
return -1;
}
int main(){
int T;scanf("%d",&T);
for(int p,a,b,x,t;T--;){
scanf("%d%d%d%d%d",&p,&a,&b,&x,&t);
if(x==t) puts("1");
else if(!a) puts(t==b?"2":"-1");
else if(a==1){
int X,Y;
int g=exgcd(b,p,X,Y);
int B=((LL)t-x+p)%p;
printf("%d\n",B%g?-1:int(((LL)B/g*X%(p/g)+p/g)%(p/g)+1));//求解线性同余方程。
}
else{
LL B=((LL)(a-1)*t+b)%p*qpow(((LL)(a-1)*x+b)%p,p-2,p)%p;
int ans=BSGS(a,B,p);
printf("%d\n",ans<0?-1:ans+1);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App