BZOJ 3122: [Sdoi2013]随机数生成器 ex_gcd+BSGS

45 篇文章 1 订阅
14 篇文章 0 订阅

传送门(^__^) 嘻嘻……
我们可以得出一个等式
(t+b/(a-1))/(x1+b/(a-1))=a^(n-1) mod p
然后我们可以发现,这是一个形如B=A^n mod C的等式,于是用BSGS求出n-1即可
因为是在mod意义下做除法,所以我们需要用到ex_gcd
详细讲解请见http://www.cnblogs.com/yuiffy/p/3877381.html


代码如下:(内含数据哦O(∩_∩)O哈!)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define int long long
using namespace std;
map<int,int> mp; 
int cas,p,a,b,x1,t;
int  ex_gcd(int aa,int bb,int &x,int &y){
    if(bb==0)
        return x=1,y=0,aa;
    int s=ex_gcd(bb,aa%bb,x,y),temp=x;
    x=y,y=temp-aa/bb*y;
    return s;
}
signed main(void){
    scanf("%lld",&cas);
    while(cas--){
        mp.clear();
        scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t);
        if(x1==t){
            cout<<1<<endl;
            continue;
        }
        if(a==0){
            if(b==t){
                cout<<2<<endl;
                continue;
            }
            else{
                cout<<-1<<endl;
                continue;
            }
        }
        if(a==1){
            if(b==0){
                cout<<-1<<endl;
                continue;
            }
            else{
                int x,y,ans;
                ex_gcd(b,p,x,y);
                ans=((((t-x1+p)%p)*x)%p+p)%p;
                cout<<ans+1<<endl;
                continue;
            }
        }
        int A=a,B,ans=-1,s,m=sqrt(p),temp1,temp2,x,y;
        ex_gcd(a-1,p,x,y),temp1=x;
        ex_gcd((x1+b*temp1%p+p)%p,p,x,y),temp2=x;
        B=(((t+b*temp1%p+p)%p)*temp2%p+p)%p;
        m+=p-m*m!=0,s=1; 
        for(int j=0;j<m;j++)
            mp[s]=j+1,s=((s*A)%p+p)%p;
        int D=1;//此时s已经是A^m 
        for(int i=0;i<m;i++){
            ex_gcd(D,p,x,y);
            x=((x*B)%p+p)%p;
            y=mp[x]-1;
            if(y!=-1){
                ans=i*m+y;
                break;
            }
            D=((D*s)%p+p)%p;
        }
        cout<<(ans==-1 ? ans : ans+1)<<endl;
    }
    return 0;
}
/*
50
7 0 4 6 6
67 0 18 24 24
11 0 10 4 10
29 0 3 17 3
41 0 1 36 27
29 0 20 24 22
59 1 0 17 17
79 1 0 76 76
59 1 0 11 56
37 1 0 4 20
29 1 10 18 26
79 1 11 48 15
23 1 1 1 13
31 1 30 0 6
67 1 54 44 38
53 1 44 30 52
47 44 0 0 0
5 4 0 0 0
23 22 0 0 15
67 59 0 0 33
29 23 6 4 27
59 47 38 26 44
29 9 27 4 6
17 5 8 2 9
29 28 15 11 22
43 15 33 0 17
7 3 1 5 1
29 14 24 8 23
41 35 28 22 0
67 16 50 30 37
29 19 25 17 22
71 0 12 7 34
67 58 5 48 42
79 18 55 49 36
79 49 33 26 72
67 65 8 38 22
5 3 3 4 3
11 3 4 4 9
2 1 1 0 1
61 38 46 57 4
43 37 36 1 17
67 57 30 63 7
37 2 35 27 22
83 58 18 15 12
67 0 57 25 4
59 40 6 42 46
31 19 4 3 17
29 23 14 26 21
5 2 3 4 0
29 17 25 3 23
*/
/*
1
1
2
2
-1
-1
1
1
-1
-1
25
77
13
26
53
28
1
1
-1
-1
3
13
-1
16
-1
-1
4
20
17
6
25
-1
2
-1
-1
-1
3
-1
2
14
-1
13
16
56
-1
36
-1
-1
3
-1
*/

by >o< neighthorn

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值