【BZOJ3122】【SDoi2013】随机数生成器

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


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\n",solve1());
87     else    if (a>=2)    printf("%lld\n",solve2());
88     }
89 }
90 
View Code

 

—Anime Otaku Save The World.
posted @ 2016-02-28 19:56  DMoon  阅读(188)  评论(0编辑  收藏  举报