poj3243 Clever Y[扩展BSGS]

Clever Y
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 8666   Accepted: 2155

Description

Little Y finds there is a very interesting formula in mathematics:

XY mod Z = K

Given XYZ, we all know how to figure out K fast. However, given XZK, could you figure out Y fast?

Input

Input data consists of no more than 20 test cases. For each test case, there would be only one line containing 3 integers XZK (0 ≤ XZK ≤ 109). 
Input file ends with 3 zeros separated by spaces. 

Output

For each test case output one line. Write "No Solution" (without quotes) if you cannot find a feasible Y (0 ≤ Y < Z). Otherwise output the minimum Y you find.

Sample Input

5 58 33
2 4 3
0 0 0

Sample Output

9
No Solution

Source

 
//消除因子,在做普通的BSGS 
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
struct Thash{
    static const ll N=1e6+5,MOD=233333;
    ll tot,val[N],h[N],next[N],head[MOD+100];
    void clear(){tot=0;memset(head,0,sizeof head);}
    void insert(ll H,ll VAL){
        for(ll i=head[H%MOD];i;i=next[i]) if(h[i]==H){val[i]=VAL;return ;}
        h[++tot]=H;val[tot]=VAL;next[tot]=head[H%MOD];head[H%MOD]=tot;
    }
    ll get(ll H){
        for(ll i=head[H%MOD];i;i=next[i]) if(h[i]==H) return val[i];
        return -1;
    }
}M;
ll gcd(ll a,ll b){
    if(!b) return a;
    return gcd(b,a%b);
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
    if(!b){d=a;x=1;y=0;return ;}
    exgcd(b,a%b,d,y,x);
    y-=a/b*x;
}
ll inv(ll a,ll p){
    ll d,x,y;
    exgcd(a,p,d,x,y);
    return d==1?(x%p+p)%p:-1;
}
ll BSGS(ll a,ll b,ll mod){
    M.clear();
    ll m=(ll)ceil(sqrt(mod+0.5));
    ll t=1;
    for(ll i=0;i<m;i++){
        M.insert(t,i);
        t=t*a%mod; 
    }
    ll base=inv(t,mod);
    ll res=b;
    for(ll i=0,z;i<m;i++){
        if((z=M.get(res))!=-1) return i*m+z;
        res=res*base%mod;
    }
    return -1;
}
ll solve(ll a,ll b,ll mod){
    ll A=1,D=1,cnt=0,ans;
    for(int i=0;i<=50;i++){
        if(A==b) return i;
        A=A*a%mod;
    }
    for(ll t;(t=gcd(a,mod))!=1;){
        if(b%t)return -1;
        b/=t;
        mod/=t;
        D*=a/t;D%=mod;
        cnt++;
    }
    b=b*inv(D,mod)%mod;
    ans=BSGS(a,b,mod);
    if(~ans) return ans+cnt;
    return -1;
}
int main(){
    ll a,b,c,ans;
    while(~scanf("%lld%lld%lld",&c,&a,&b)){
        ans=solve(a,b%c,c);
        if(~ans) printf("%lld
",ans);
        else puts("no solution");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/6598929.html