互质:原地址

洛谷P3846模板:

//x的多少次方同余于y (mod p)
//将x拆分 移项
#include<bits/stdc++.h>
using namespace std;
map<int,int> mp;
int x,y,mod;
int quick_pow(int a,int k)
{
    int ans=1;
    while(k){ if(k&1) ans=1ll*ans*a%mod; k>>=1; a=1ll*a*a%mod; }
    return ans;
}
int main()
{
    scanf("%d%d%d",&mod,&x,&y);
    if(x%mod==0&&y) {puts("no solution");return 0;}//记得要特判 
    //+1是因为sqrt向下取整 有可能最大值达不到mod 
    int m=sqrt(mod)+1,left=y;//left的初始值是式子右边的y 因为这时m=0 
    for(int j=0;j<=m-1;j++)//枚举j  j是i*m-j的j 
     mp[left]=j,left=1ll*left*x%mod;
    int t=quick_pow(x,m),s=1;
    for(int i=1;i<=m;i++){
        s=1ll*s*t%mod;//map查找元素的操作:mp.count() 复杂度比hash多了一个log 
        if(mp.count(s)) { printf("%d\n",m*i-mp[s]); return 0; }
    }
    printf("no solution\n");
}
/*
5 2 3
ans 3
*/
互质

 

不互质:先消因子,再用原BSGS

洛谷P4195模板:

//洛谷要开O2才过的了。。。
/*
思路:对于模数不是质数的情况 先消除因子 再用原BSGS解决
取gcd(a,p)  用b与p约去约数  
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll p;
map<ll,ll> mp;
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; }
ll quick_pow(ll a,ll k)
{
    ll ans=1;
    while(k){
        if(k&1) ans=ans*a%p;
        a=a*a%p;
        k>>=1;
    }
    return ans;
}
ll exbsgs(ll a,ll b)
{
        a%=p;b%=p; ll c=1;
        if(b==1)return 0;
        for(ll i=0;i<=30;i++)//先暴+力处理前面小于cnt
        if(quick_pow(a,i)%p==b%p) return i;
        ll cnt=0;//消除因子
        for(ll g=gcd(a,p);g!=1;g=gcd(a,p)){
            if(b%g) return -1;
            b/=g;p/=g;c=c*(a/g)%p;cnt++;
            if(b==c) return cnt;//说明找到一个可行解cnt  a^cnt/x^cnt(=)b/x^cnt   (=)为同余
        }
        mp.clear();
        ll m=(ll)sqrt(p)+1,left=b;//下面是原bsgs 现在方程已经化简成:d*a^(ans-cnt)(=)b(mod p)  d*a^(ans-cnt)其实等于a^x
        for(ll j=0;j<m;j++){
            mp[left]=j;
            left=left*a%p;
            //用mp会多一个log
        }
        left=quick_pow(a,m)%p;
        for(ll i=1;i<=m+1;i++){
            c=c*left%p; 
            if(mp.count(c))return i*m-mp[c]+cnt;//+cnt是因为求出来的是ans-cnt 由上面的方程可知
        }
        return -1;
}
int main()
{
    while(1){
        ll a,b;
        scanf("%lld%lld%lld",&a,&p,&b);
        if(p==0) break;
        ll ans=exbsgs(a,b);
        if(ans!=-1)
        printf("%lld\n",ans);
        else printf("No Solution\n");
    }
    return 0;
}
扩展

 

posted on 2019-07-31 15:55  rua-rua-rua  阅读(246)  评论(0编辑  收藏  举报