BZOJ 1467&&2480;3239 扩展BSGS

来源:互联网 发布:小数点的算法 编辑:程序博客网 时间:2024/06/04 20:14

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;}

这里写图片描述