首页 > 代码库 > BZOJ 3122 SDOI2013 随机数生成器 数论 EXBSGS
BZOJ 3122 SDOI2013 随机数生成器 数论 EXBSGS
题目大意:给定一个数列X(i+1)=(a*Xi+b)%p 求最小的i>0,使Xi=t
0.0 此题能1A真是太好了
首先讨论特殊情况
若X1=t ans=1
若a=0 ans=b==t?2:-1
若a=1 X1+b*(ans-1)==t (%p) 扩展欧几里得
令
temp=b/(a-1)
则有
(X(i+1)+temp)=a*(Xi+temp)
Xans=(X1+temp)*a^(ans-1)-temp
其中Xans%p=t
则有
(X1+temp)*a^(ans-1)-temp == t (%p)
两侧同乘a-1得
(a*X1-X1+b)*a^(ans-1) == (a-1)*t+b (%p)
令
Y=a*X1-X1+b
Z=a*t-t+b
Y*a^(ans-1) == Z(%p)
将Y和p约分
若Z%gcd(Y,p)!=0 return -1
令
A=a
B=Z*Y^-1
C=p
x=ans-1
A^x==B(%C)
然后就是EXBSGS的模板了0.0 这个模板我再也不想打第二遍了0.0
代码没法看了,诸位理解算法思想就好了0.0
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1001001 using namespace std; typedef long long ll; typedef pair<ll,ll> abcd; ll X,Y,Z,a,b,c,p,t,A,B,C,D; ll hash_table[M],val[M],tim[M],tot; int Hash(ll x) { int pos=x%M; while(1) { if(tim[pos]!=tot) tim[pos]=tot,hash_table[pos]=-1,val[pos]=0x3f3f3f3f; if(hash_table[pos]==-1||hash_table[pos]==x) return hash_table[pos]=x,pos; else ++pos,pos%=M; } } int Get_Hash(ll x) { int pos=x%M; while(1) { if(tim[pos]!=tot) tim[pos]=tot,hash_table[pos]=-1; if(hash_table[pos]==-1) return -1; if(hash_table[pos]==x) return pos; else ++pos,pos%=M; } } ll GCD(ll x,ll y) { return y?GCD(y,x%y):x; } abcd EXGCD(ll x,ll y) { if(!y) return abcd(1,0); abcd temp=EXGCD(y,x%y); return abcd(temp.second,temp.first-x/y*temp.second); } ll Inverse(ll x) { ll temp=EXGCD(x,C).first; return (temp%C+C)%C; } ll Extended_Big_Step_Giant_Step() { ll i,m,cnt=0,temp,base=1; int pos; if(B>=C) return -1; for(i=0,temp=1%C;i<=50;i++,temp*=A,temp%=C) if(temp==B) return i; D=1; while(temp=GCD(A,C),temp!=1) { if(B%temp) return -1; ++cnt; B/=temp; C/=temp; D*=A/temp; D%=C; } B*=Inverse(D);B%=C; m=(ll)ceil(sqrt(C)+1e-5); ++tot; for(i=0,temp=1%C;i<m;i++,temp*=A,temp%=C) pos=Hash(temp),val[pos]=min(val[pos],i); for(i=1,base=1%C;i<=m;i++,base*=A,base%=C); for(i=0,D=1%C;i<m;i++,D*=base,D%=C) { temp=EXGCD(D,C).first*B; temp=(temp%C+C)%C; pos=Get_Hash(temp); if(~pos) return i*m+val[pos]+cnt; } return -1; } ll Deal() { ll temp; cin>>p>>a>>b>>X>>t; if(X==t) return 1; if(!a) return b==t?2:-1; if(a==1) { t+=p-X;t%=p; //b*(ans-1)==t (%p) temp=GCD(b,p); if(t%temp) return -1; b/=temp;t/=temp;p/=temp; temp=(EXGCD(b,p).first*t%p+p)%p; return temp+1; } Y=(a*X-X+b)%p; Z=(a*t-t+b)%p; temp=GCD(Y,p); if(Z%temp) return -1; Y/=temp;Z/=temp;p/=temp; C=p; B=Z*Inverse(Y)%p; A=a; temp=Extended_Big_Step_Giant_Step(); if(temp==-1) return -1; return temp+1; } int main() { int T; for(cin>>T;T;T--) cout<<Deal()<<endl; }
BZOJ 3122 SDOI2013 随机数生成器 数论 EXBSGS
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。