BZOJ 1467&&2480;3239 扩展BSGS

13 篇文章 0 订阅

2480: Spoj3105 Mod

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 797   Solved: 273
[ Submit][ Status][ Discuss]

Description

已知数a,p,b,求满足a^x≡b(mod p)的最小自然数x。

 

Input

    每个测试文件中最多包含100组测试数据。
    每组数据中,每行包含3个正整数a,p,b。
    当a=p=b=0时,表示测试数据读入完全。
 

Output

 
    对于每组数据,输出一行。
    如果无解,输出“No Solution”(不含引号),否则输出最小自然数解。
 

Sample Input

5 58 33
2 4 3
0 0 0

Sample Output

9
No Solution

HINT

  100%的数据,a,p,b≤1e9。
2016.3.29新加数据一组 by  1430586275

Source

思考

扩展BSGS

作用

BSGS只能处理C是素数的情况,太特殊了,应用范围不大。而扩展BSGS可以解决C不是素数的一般情况。

方法

设d=gcd(A,C),那么A,B,C可以表示为A=a*d,B=b*d(如果B不是d的倍数且B!=1则显然无解),C=c*d。也就是说(ad)xbd(mod
根据同余性质,这个式子可以同除d,得到a(ad)x1b(mod),D*=A/d,num++,直到d=1为止。

最后方程就变成这种形式了:DAxnumB(mod,所以x将会>=num,这就导致0~num-1枚举不到。所以要在最开始枚举一下0~num-1,这个问题就解决了。

学习一下ex_gcd的灵活运用,吐槽因为有了ex_gcd导致我们还要学习扩展CRT与扩展BSGS…………
就是与扩展CRT几乎一样的思路,将非质数拆分后处理。

//1467与2480的双倍经验,修改一下输入输出就可以过3239
#include<map>
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
map<long long,long long> hash;
long long gcd(long long a,long long b){return b==0?a:gcd(b,a%b);}
void exgcd(long long a,long long b,long long &x,long long &y){
    if(!b) {x=1;y=0;return;}
    exgcd(b,a%b,y,x);y-=x*(a/b);
}
long long inv(long long a,long long p){if(!a) return 1;long long x,y;exgcd(a,p,x,y);return (x%p+p)%p;}
long long pow(long long a,long long b,long long p){
    long long ret=1;
    while(b){
        if(b&1)ret=ret*a%p;
        a=a*a%p;b>>=1;
    }
    return ret;
}
long long BSGS(long long a,long long b,long long p){
    if(a==0)return b==0?1:-1;
    b%=p;a%=p;
    hash.clear();
    long long cnt=0;
    for(int g=gcd(a,p);g!=1;g=gcd(a,p)){
        if(b%g) return -1;
        b/=g;p/=g;b=b*inv(a/g,p)%p;
        cnt++;
        if(b==1)return cnt;
    }
    if(p==1)return cnt;
    int m=(int)sqrt(p)+1;
    long long e=1;hash[e]=0;
    long long v=inv(pow(a,m,p),p);
    for(int i=1;i<m;i++){
        e=e*a%p;
        if(!hash.count(e))hash[e]=i;
    }
    for(int i=0;i<=m;i++){
        if(hash.count(b))return i*m+hash[b]+cnt;
        b=b*v%p;
    }
    return -1;
}
long long a,b,p;
int main(){
    while(cin>>a>>p>>b&&p){
        long long t=BSGS(a,b,p);
        if(t==-1)puts("No Solution");
        else cout<<t<<endl;
    }
    return 0;
}

这里写图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值