您的位置:首页 > 其它

【SDOI2013】【BZOJ】【P3122】【随机数生成器】【Baby Step Giant Step】

2014-02-09 21:00 399 查看
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3122

题解:

把数列化简:

x[i+1]=ax[i]+b(mod p)

==>x[i+1]+b/(a-1)=a(x[i]+b/(a-1))] (mod p)

==>x[t]+b/(a-1)=a^(t-1)(x1+b/(a-1)) (mod p)

==>(x[t]+b*inv(a-1))*inv(x1+b*inv(a-1))=a^(t-1)(mod p)  inv表示逆元

然后Baby Step Giant Step

注意a=1 a=0 b=0  x1=xn等特判

奇丑无比的代码:

/*
ID:zky
OJ:BZOJ
Index:3122
Language:C++
*/
#include<map>
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long lld;
lld x1,xn,a,b,p;

map<lld,lld>hash;
lld power(lld x,lld k,lld p){
lld res=1;
if(k==0)return 1;
res=power(x,k/2,p)%p;
res=(res%p)*(res%p)%p;
if(k&1)res=(res%p)*(x%p)%p;
return res;
}
lld inv(lld x){
return power(x,p-2,p);
}
void work3(){
//xn=(a*x1+b)%p
//==>xn+b/(a-1)=a^(t-1)*(x1+b/(a-1)) mod p
//==>(xn+b*inv(a-1))*inv(x1+b*inv(a-1))=a^(t-1)mod p
//==>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lld tmp=b*inv(a-1)%p;
xn=(xn+tmp)%p;
x1=(x1+tmp)%p;
lld N=xn*inv(x1)%p;

a%=p;N%=p;
if(!a&&!N){
cout<<1<<endl;
return;
}
if(!a){
cout<<-1<<endl;
return;
}
//a^(t-1)=N(mod p)
//solve t!
//k=t-1
//k=im+j
//for j=0 -> m-1 in hash
//a^im*a^j=N(mod p)
//v=inv(a^m)=power(a,p-m-1,p)
//a^j=N*v^i(mod p) for i,watch j in hash

lld m=ceil(sqrt(p));
lld v=power(a,p-m-1,p);
lld ans=-1;
hash[1]=m+1;
lld e=a;
for(int j=1;j<=m;j++){
if(!hash[e])hash[e]=j;
e=(e%p*(a%p))%p;
}
for(int i=0;i<m;i++){
lld j=hash
;
if(j){
if(j==m+1)j=0;
ans=i*m+j;
break;
}
N=(N*v)%p;
}
hash.clear();
if(ans==0){
cout<<p<<endl;
return;
}
if(ans==-1)
cout<<ans<<endl;
else
cout<<ans+1<<endl;

}
void exgcd(lld a,lld b,lld &x,lld &y){
if(b==0){
x=1;y=0;
}else{
exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
}
}
lld gcd(lld a,lld b){
if(!b)return a;return gcd(b,a%b);
}
void work2(){
lld n=xn-x1+b;
lld d=gcd(b,p);
if(n%d){
cout<<-1<<endl;
return;
}
lld r,s;
exgcd(b,p,r,s);
r=r*n/d;
r=(r+p)%p;
while(r<=0)r+=p;
//while(r<0)r+=p;
cout<<r<<endl;
}
void work(){
lld z=xn%p*inv(x1)%p;
lld y=a;
y%=p;z%=p;
if(!y&&!z){cout<<"1"<<endl;return;}
if(!y){cout<<"-1"<<endl;return;}
lld m=ceil(sqrt(p));
lld v=power(y,p-m-1,p);
lld e=1;
hash[1]=m+1;
for(lld i=1;i<=m;i++){
e=(e*y)%p;
if(!hash[e])hash[e]=i;
}
lld ans=-1;
for(lld i=0;i<m;i++){
lld j=hash[z];
if(j){
if(j==m+1)j=0;
ans=i*m+j;
break;
}
z=(z*v)%p;//
}
hash.clear();
if(ans==0){
cout<<p<<endl;
return;
}
if(ans==-1)cout<<"-1"<<endl;
else cout<<ans+1<<endl;

}
int main(){
lld T;
cin>>T;
while(T--){
cin>>p>>a>>b>>x1>>xn;
if(x1==xn){
cout<<1<<endl;
continue;
}
if(a==0&&b==0){
cout<<-1<<endl;
continue;
}else
if(a==0){
if(xn%p==x1%p)cout<<1<<endl;
else if(xn==b)cout<<2<<endl;
else cout<<-1<<endl;
continue;
}else
if(a==1&&b==0){
if(x1==xn)cout<<1<<endl;
else cout<<-1<<endl;
continue;
}else
if(a==1){
work2();
continue;
}else if(b==0){
work();
}
else work3();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj