bzoj3122: [Sdoi2013]随机数生成器
继前几天靠星球联盟混到400t之后靠这题神仙题混到了rk600-
……太神仙了,谁会想到柿子两边同时加一个b/(a-1)?? 这个等效替换估计出题人就是某省数竟+信竟选手 寄刀片
按这个画完柿子以后就变成 a^(n-1)=(xn+b/(a-1)) / ((x1+b*(a-1))
上BSGS
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<map> using namespace std; typedef long long LL; LL p; LL quick_pow(LL A,LL pp) { LL ret=1; while(pp!=0) { if(pp%2==1)ret=(ret*A)%p; A=(A*A)%p;pp/=2; } return ret; } LL getinv(LL A){return quick_pow(A,p-2);} LL getB(LL a,LL b,LL x1,LL xn){return ((xn+b*getinv(a-1)%p)%p) * getinv((x1+b*getinv(a-1)%p)%p) %p;} map<LL,LL>Hash; LL BSGS(LL a,LL b) { Hash.clear(); a%=p;b%=p; if(a==0)return (b==0)?1:-2; LL t=(LL(sqrt(double(p+1))))+1,k=1; for(int j=0;j<t;j++) { Hash[b*k%p]=j;//b*a^j k=(k*a)%p; } a=quick_pow(a,t);//a^t k=a; for(int i=1;i<=t;i++) { if(Hash.find(k)!=Hash.end()) { LL j=Hash[k]; if(t*i-j>=0)return t*i-j; } k=(k*a)%p; } return -2; } int main() { int T; scanf("%d",&T); while(T--) { LL a,b,x1,xn; scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&xn); if(x1==xn){printf("1\n");continue;} if(a==0) { if(xn==b)printf("2\n"); else printf("-1\n"); continue; } if(a==1) { if(b==0) { if(xn==x1)printf("1\n"); else printf("-1\n"); } else printf("%d\n",((xn-x1+p)%p)*getinv(b)%p+1); continue; } printf("%lld\n",BSGS(a,getB(a,b,x1,xn))+1); } return 0; }
pain and happy in the cruel world.