Description
Input
输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数。
接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据。保证X1和t都是合法的页码。
注意:P一定为质数
Output
共T行,每行一个整数表示他最早读到第t页是哪一天。如果他永远不会读到第t页,输出-1。
Sample Input
3
7 1 1 3 3
7 2 2 2 0
7 2 2 2 1
7 1 1 3 3
7 2 2 2 0
7 2 2 2 1
Sample Output
1
3
-1
HINT
0<=a<=P-1,0<=b<=P-1,2<=P<=10^9
Source
Solution:多种情况a=0:。。。
a=1:EXGCD
a=2:一些神奇的化简什么的,可以化简到使用BSGS的地步,贴上YveH大爷的blog。
注意各种特判。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <map> 5 #define ll long long 6 using namespace std; 7 ll a,b,p,x1,t; 8 ll fast_pow(ll x,ll y,ll q) 9 { 10 ll ans=1; 11 while (y) 12 { 13 if (y&1) ans=ans*x%p; 14 x=x*x%p; 15 y>>=1; 16 } 17 return ans; 18 } 19 20 ll ex_gcd(ll a,ll b,ll &x1,ll &y1) 21 { 22 if (b==0) {x1=1;y1=0;return a;} 23 ll ans=ex_gcd(b,a%b,x1,y1); 24 ll temp=x1; x1=y1; y1=temp-a/b*y1; 25 return ans; 26 } 27 28 ll bsgs(ll A,ll n,ll q) 29 { 30 A%=q; n%=q; 31 if (!A && !n) return 1; 32 if (!A) return -1; 33 map<ll,ll> mp; 34 ll m=ceil(sqrt(q)); 35 ll temp=fast_pow(A,m,q),k=n%q; 36 mp.clear(); 37 for (int i=1;i<=m;i++) 38 { 39 k=k*A%q; 40 if (!mp[k]) mp[k]=i; 41 } 42 k=1; 43 for (int i=1;i<=m;i++) 44 { 45 k=k*temp%q; 46 if (mp[k]) 47 { 48 if (mp[k]==-123) mp[k]=0; 49 return m*i-mp[k]; 50 } 51 } 52 return -1; 53 } 54 55 ll solve1() 56 { 57 ll C=(t-x1+p)%p,x,y; 58 ll d=ex_gcd(b,p,x,y); 59 if (C%d) return -1; 60 x=x*C/d%p; 61 while (x<0) x+=p; 62 return x+1; 63 } 64 65 ll solve2() 66 { 67 ll c=fast_pow(a-1,p-2,p)%p,B=(x1+b*c)%p,C=(b*c+t)%p,x,y; 68 ll d=ex_gcd(B,p,x,y); 69 if (C%d) return -1; 70 while (x<0) x+=p; 71 ll temp=bsgs(a,x*C/d%p,p); 72 if (temp!=-1) return temp+1; 73 else return -1; 74 } 75 76 int main() 77 { 78 int T; 79 scanf("%d",&T); 80 while (T--) 81 { 82 scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t); 83 if (x1==t) puts("1"); 84 else if (a==0) if (b==t) puts("2"); 85 else puts("-1"); 86 else if (a==1) printf("%lld ",solve1()); 87 else if (a>=2) printf("%lld ",solve2()); 88 } 89 } 90