标签:
输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数。
接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据。保证X1和t都是合法的页码。
注意:P一定为质数
共T行,每行一个整数表示他最早读到第t页是哪一天。如果他永远不会读到第t页,输出-1。
0<=a<=P-1,0<=b<=P-1,2<=P<=10^9
扩展欧几里得求逆元+BSGS
题解戳这里:http://hzwer.com/6963.html
(公式恐惧症飘过,不带走一片云彩)
注意各种特殊情况的判断,WA了很多次...
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<map> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long using namespace std; ll T,p,a,b,x1,t; map<ll,int> mp; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline ll getpow(ll x,ll y,ll p) { ll ret=1; for(;y;y>>=1,x=x*x%p) if (y&1) ret=ret*x%p; return ret; } inline ll exgcd(ll a,ll b,ll &x,ll &y) { if (!b){x=1;y=0;return a;} ll ret=exgcd(b,a%b,x,y); ll t=x;x=y;y=t-a/b*y; return ret; } inline ll bsgs(ll a,ll b,ll p) { if (b==1) return p-1; ll m=ceil(sqrt(p)); mp.clear(); ll tmp=1,inv=getpow(a,p-2,p); F(i,0,m) { ll h=b*tmp%p; if (!mp[h]) mp[h]=i; tmp=tmp*inv%p; } tmp=1; ll base=getpow(a,m,p); F(i,0,m) { if (mp[tmp]) { ll ret=i*m+mp[tmp]; return ret; } tmp=tmp*base%p; } return -1; } inline ll calc1() { ll c=((t-x1)%p+p)%p,x,y; ll tmp=exgcd(b,p,x,y); if (c%tmp) return -1; return (x*c/tmp%p+p)%p+1; } inline ll calc2() { ll c=getpow(a-1,p-2,p); ll t1=(b*c%p+x1)%p,t2=(b*c%p+t)%p,x,y; if (t1==0) { if (t2==0) return 1; else return -1; } if (t2==0) return -1; ll tmp=exgcd(t1,p,x,y); if (t2%tmp) return 0; t2/=tmp;x=(x%p+p)%p; ll t=bsgs(a,x*t2%p,p); if (t==-1) return -1; else return t+1; } inline ll getans() { if (x1==t) return 1; if (a==0) return b==t?2:-1; if (a==1) return calc1(); return calc2(); } int main() { int T=read(); while (T--) { p=read();a=read();b=read();x1=read();t=read(); printf("%lld\n",getans()); } }
标签:
原文地址:http://blog.csdn.net/aarongzk/article/details/51138647