【BSGS】Discrete Logging

题目描述

Given a prime P,2<=P<231P, 2 <= P < 2^{31}P,2<=P<231​​, an integer B,2<=B<PB, 2 <= B < PB,2<=B<P, and an integer N,1<=N<PN, 1 <= N < PN,1<=N<P, compute the discrete logarithm of NNN, base BBB, modulo PPP. That is, find an integer LLL such that

BL==N(modP)B^L == N (mod P)BL​​==N(modP)

输入格式

Read several lines of input, each containing P,B,NP,B,NP,B,N separated by a space,

输出格式

For each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".

样例

样例输入

5 2 1
5 2 2
5 2 3
5 2 4
5 3 1
5 3 2
5 3 3
5 3 4
5 4 1
5 4 2
5 4 3
5 4 4
12345701 2 1111111
1111111121 65537 1111111111

样例输出

0
1
3
2
0
3
1
2
0
no solution
no solution
1
9584351
462803587

数据范围与提示

The solution to this problem requires a well known result in number theory that is probably expected of you for Putnam but not ACM competitions. It is Fermat's theorem that states

B(P−1)==1(modP)

for any prime PPP and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat's theorem is that for any m

B(−m)==B(P−1−m)(modP)

背景

  这题的英文题面是真的没有翻译!!!!

  差评。

  看懂题面简直费死劲了。

  结果还是导致了理解偏差QAQ,发此博客献给我的英语老师 Mr.jia


 

思路分析

  ? 你们知道北上广深嘛?

  指 BSGS算法 ,我今日的研究成果。

  其实如果知道这个算法,那么这道题就只是个代码实现了。【确认过,是板子

  那么我来具体介绍一下这个算法。

  BSGS

    明确:BSGS用于求解高次同余方程的整数解。

          

    上面就是一个高次同余方程。

    我们来思考一下,有没有什么定理啊,推论啊能够化简这个式子。

  ·   在求解这个问题之前,我们先假设A与C互质。【A和C不互质的情况,先进行消因子处理成互质的。

    然后,根据费马小定理可以得到 :

      当A和C互质的时候,有如下:

        

      所以循环节的长度不会大于c,即数据小的时候,可以枚举 0≤x≤c-1

    那么,数据大了怎么办呢?

    这就要用到BSGS了。

      

    具体就是代码实现了。


 

代码实现

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#define ll long long 
#define rint register int 
using namespace std;

ll p,b,n;
map<ll,int> hash;

ll fpow(ll x,ll b) {
    ll res=1;
    while(b) {
        if(b&1) {
            res*=x;
            res%=p;
        }
        b>>=1;
        x*=x;
        x%=p;
    }
    return res;
}

int main()
{
    while(scanf("%lld%lld%lld",&p,&b,&n)!=EOF) {
        if(!(b%p)) {
            cout<<"no solution"<<endl;
            continue;
        }
        hash.clear();
        ll m=ceil(sqrt(p));
        ll ans=0;
        for(rint i=0;i<=m;i++) {
            if(!i) {
                ans=n%p;
                hash[ans]=i;
                continue;
            }
            ans=ans*b%p;
            hash[ans]=i;
        }
        ans=1;
        bool flag=false;
        for(rint i=1;i<=m;i++) {
            ans=(ans*fpow(b,m))%p;
            if(hash[ans]) {
                ans=i*m-hash[ans];
                ans=(ans%p+p)%p;
                printf("%lld\n",ans);
                flag=true;
                break;
            }
        }
        if(!flag) 
            cout<<"no solution"<<endl;
    }
    return 0;
}

 

 

posted @ 2019-07-21 21:32  鸽子咕  阅读(140)  评论(0编辑  收藏  举报