[luogu4195 Spoj3105] Mod (大步小步)

传送门

题目描述

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

输入输出格式

输入格式:
每个测试文件中最多包含100组测试数据。

每组数据中,每行包含3个正整数a,p,b。

当a=p=b=0时,表示测试数据读入完全。

输出格式:
对于每组数据,输出一行。

如果无解,输出“No Solution”(不含引号),否则输出最小自然数解。

输入输出样例

输入样例#1:
5 58 33
2 4 3
0 0 0
输出样例#1:
9
No Solution

说明

100%的数据,a,p,b≤1e9。

题解

大步小步模板

code:(在luogu不开氧气过不了QAQ)

#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define M(a,b) memset(a,(b),sizeof(a))
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define C(i,a,b) for(int i=(b);i>=(a);i--)
#define E(i,u) for(int i=head[u];i;i=nex[i])
using namespace std;

LL rd() {
    LL x=0,f=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-') f=-f;c=getchar();}
    while(isdigit(c)) x=(x<<3)+(x<<1)+c-48,c=getchar();
    return x*f;
}

LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}

LL qpow(LL a,LL b,LL p) {
    LL ans=1;
    while(b) { if(b&1) ans=a*ans%p; a=a*a%p; b>>=1; }
    return ans;
}

int BSGS(int a,int b,int p) {
    a%=p,b%=p; if(b==1) return 0;
    int cnt=0; LL t=1;
    for(int g=gcd(a,p);g!=1;g=gcd(a,p)) {
        if(b%g) return -1;
        p/=g,b/=g; t=t*a/g%p; cnt++;
        if(b==t) return cnt;
    }
    map <LL,int> M;
    int m=int(sqrt(1.0*p)+1); LL tmp=b;
    F(i,0,m) M[tmp]=i,tmp=tmp*a%p;
    tmp=qpow(a,m,p);
    LL now=t;
    F(i,1,m+1) {
        now=now*tmp%p;
        if(M.count(now)) return i*m-M[now]+cnt;
    }
    return -1;
}

int main() {
    int a,b,p;
    while(~scanf("%d %d %d",&a,&p,&b)&&p) {
        int ans=BSGS(a,b,p);
        if(ans==-1) puts("No Solution");
        else printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Menteur-Hxy/p/9251985.html
mod
今日推荐