【bzoj3122】[Sdoi2013]随机数生成器 BSGS

来源:互联网 发布:sip协议端口号 编辑:程序博客网 时间:2024/05/29 08:45
xi=axi+b
特判x1是否等于t
当a=0时,xi=b,直接判断t是否等于b
当a=1时,xi=x1+(i-1)*b=t,特判b是否等于0,i=(t-x1)*b^(-1)+1
当b=0时,xi=x1*a^(i-1)=t,如果x1或a=0,则判断t是否等于0,否则,BSGS
否则,
xi=axi-1+b
xi+b/(a-1)=axi-1+ab/(a-1)
xi+b/(a-1)=a(xi-1+b/(a-1))
xi+b/(a-1)=(x1+b/(a-1))*a^(i-1)
xi=(x1+b/(a-1))*a^(i-1)-b/(a-1)
可以看做a^y=z(mod p)的形式
z=(t+b*(a-1)^(-1))*(x1+b*(a-1)^(-1))^(-1)

y=i-1<=>i=y+1


#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<iostream>#include<map>using namespace std;long long a,b,x1,t,mod;int T;map<long long,int> mp;long long power(long long x,long long y,long long mod){long long ans=1;while (y){if (y&1) ans=ans*x%mod;x=x*x%mod;y>>=1;}return ans;}int BSGS(long long y,long long z,long long mod){if (y==0 && z==0) return 1;if (y==0 && z!=0) return -2;mp.clear();long long temp=z,p=power(y,mod-2,mod);int k=ceil(sqrt(mod));mp[z]=k+1;for (int i=1;i<k;i++){temp=temp*p%mod;if (!mp[temp]) mp[temp]=i;}temp=1;p=power(y,k,mod);for (int i=0;i<k;i++,temp=temp*p%mod){if (mp[temp]){if (mp[temp]==k+1) return i*k;else return i*k+mp[temp];}}return -2;}int main(){scanf("%d",&T);while (T--){scanf("%lld%lld%lld%lld%lld",&mod,&a,&b,&x1,&t);if (x1==t) {printf("1\n");continue;}if (a==0){if (t==b) printf("2\n"); else printf("-1\n");continue;}if (a==1) {if (b) printf("%d\n",((t-x1+mod)%mod)*power(b,mod-2,mod)%mod+1);else{if (t==x1) printf("1\n");else printf("-1\n");}continue;}long long tmp=power(a-1,mod-2,mod);printf("%d\n",BSGS(a,((t+b*tmp)%mod)*power((x1+b*tmp)%mod,mod-2,mod)%mod,mod)+1);}return 0;}


0 0
原创粉丝点击