[SDOI2013]随机数生成器(BSGS)
作者:互联网
这题妙啊,我们做这道题遇到的首先一个门槛就是推式子:
\[
X_{i+1}=aX_{i}+b
\]
我们考虑两边同时加上\(\frac{b}{a-1}\),这样我们就构造出了一个等比数列:
\[
X_{i+1}+\frac{b}{a-1}=a(X_i+\frac{b}{a-1})(mod\:p)
\]
然后就是简单的等比数列求第\(n\)项:
\[
X_{n}+\frac{b}{a-1}=a^{n-1}(X_1+\frac{b}{a-1})(mod\:p)
\]
上式只有\(n\)是未知的,我们移项可得:
\[
a^{n-1}\equiv(X_n+b*inv(a-1))*inv(X_1+b*inv(a-1))(mod\:p)
\]
我们求\(n\)就直接用bsgs就好了,注意明显的特殊数据就直接特判输出答案,看代码
#pragma GCC optimize(2)
#pragma G++ optimize(2)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T,C;
ll powmod(ll x,ll y,ll mod)
{
ll sum=1;
while(y)
{
if(y&1)
{
sum=sum*x%mod;
}
x=x*x%mod;
y>>=1;
}
return sum;
}
map<ll,ll> mp;
void bsgs(ll x,ll y,ll mod)
{
ll i,j;
if(x%mod==0)
{
printf("-1\n");
return;
}
mp.clear();
ll m=sqrt(mod)+1,t,tt;
for(i=0,t=y;i<m;++i,t=t*x%mod) mp[t]=i;
for(i=1,tt=powmod(x,m,mod),t=tt;i<=m;i++,t=t*tt%mod)
{
j=mp.find(t)==mp.end()?-1:mp[t];
if(j>=0&&i*m-j>=0)
{
printf("%lld\n",i*m-j+1);
return;
}
}
printf("-1\n");
}
int main()
{
ll i,j,p,a,b,X1,t;
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&X1,&t);
if(X1==t){puts("1");continue;}
if(a==0){puts(t==b?"2":"-1");continue;}
if(a==1&&b==0){puts("-1");continue;}
if(a==1){
ll ny=powmod(b,p-2,p);
ll ans=((((t-X1)%p+p)%p)*ny%p)%p;
printf("%lld\n",ans+1);continue;
}
ll u=b%p*powmod(a-1,p-2,p);
ll cc=(X1+u)%p;
C=(t+u)%p*powmod(cc,p-2,p)%p;
bsgs(a,C%p,p);
}
return 0;
}
标签:powmod,frac,ll,生成器,SDOI2013,BSGS,return,X1,mod 来源: https://www.cnblogs.com/yzxx/p/11700388.html