BZOJ-3122 [Sdoi2013]隨機數生成器(BSGS)
阿新 • • 發佈:2020-11-16
題目描述
有四個引數 \(p,a,b,x_1\),滿足 \(0\leq a,b,x_1<p\),按照下面的式子生成一系列整數:
\[x_{i+1}\equiv a\times x_i+b\pmod {p} \]給出一個數字 \(t\),求出 \(x_i=t\) 的最小下標 \(i\)。
資料範圍:\(1\leq T\leq 50,0\leq a,b,x_1,t<p,2\leq p\leq 10^9\),\(p\) 為質數。
分析
\[x_{i+1}\equiv ax_i+b\pmod {p}\\ x_{i+1}+\frac{b}{a}\equiv ax_{i}+b+\frac{b}{a}\pmod {p}\\ ax_{i+1}+b\equiv a^2x_{i}+ab+b\pmod {p}\\ x_{i+2}\equiv a^2x_{i}+ab+b\pmod {p} \]則:
\[x_2\equiv ax_1+b\pmod {p}\\ x_{3}\equiv a^2x_{1}+ab+b\pmod {p}\\ x^4\equiv a^3x_1+a^2b+ab+b\pmod p\\ \cdots\\ x_{i}\equiv a^{i-1}x_1+b(a^{i-2}+a^{i-1}+\cdots+a+1)\equiv a^{i-1}x_1+b\sum_{k=0}^{i-2}a^{k}\pmod {p} \]即判斷關於 \(i\) 的方程 \(t\equiv a^{i-1}x_1+b\displaystyle\sum_{k=0}^{i-2}a^{k}\pmod {p}\)
用 \(\text{BSGS}\) 演算法求解即可。
注意:當 \(t=x_1\)
程式碼
#include<bits/stdc++.h>
using namespace std;
long long p,a,b,x1,t;
long long quick_pow(long long a,long long b,long long p)
{
long long ans=1;
while(b)
{
if(b&1)
ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
map<long long,long long> mp;
long long BSGS(long long a,long long b,long long p)
{
a=a%p,b=b%p;
long long m=sqrt(p)+1;
long long ans=b;
for(long long i=0;i<m;i++)
{
mp[ans]=i;
ans=ans*a%p;
}
long long temp=quick_pow(a,m,p);
ans=1;
for(long long i=1;i<=m;i++)
{
ans=1ll*ans*temp%p;
if(mp.count(ans))
return i*m-mp[ans];
}
return -1;
}
int main()
{
int T;
cin>>T;
while(T--)
{
mp.clear();
scanf("%lld %lld %lld %lld %lld",&p,&a,&b,&x1,&t);
if(t==x1)
{
puts("1");
continue;
}
if(a==0)
{
if(b==t)
puts("2");
else
puts("-1");
continue;
}
if(a==1)
{
t=((t-x1)%p+p)%p;
if(t%__gcd(b,p)!=0)
puts("-1");
else
{
if((t*quick_pow(b,p-2,p)+1)%p==0)
cout<<p<<endl;
else
cout<<(t*quick_pow(b,p-2,p)+1)%p<<endl;
}
continue;
}
long long fz=((t-b*quick_pow(1-a,p-2,p)%p)+p)%p;
long long fm=quick_pow(((x1-b*quick_pow(1-a,p-2,p))%p+p)%p,p-2,p);
long long ans=BSGS(a,fz*fm%p,p);
if(ans==-1)
puts("-1");
else
cout<<ans+1<<endl;
}
return 0;
}