[模板] BSGS

BSGS是一种解决一类专门的问题的解法,主要是解决已知A, B, C,求X使得A^x = B (mod p)这一类问题。

解法很简单,先设x = i*m-j(m=ceil(sqrt(p))),然后进行变形,得到ai*m = b*aj (mod p)。

先枚举j (范围0-m) ,将 b*aj  存入hash表。再枚举i (范围1-m) ,从hash表中寻找第一个满足ai*m = b*aj  (mod p)。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;i++)
#define lv(i,a,n) for(register int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
map <ll,int> mp;
ll t,m,n,ans,now;
ll p,a,b;
bool flag;
ll qpow(ll a,ll b)
{
    ll sum = 1;
    while(b)
    {
        if(b % 2 == 1)
        {
            sum *= a;
        }
        a *= a;
        sum %= p;
        a %= p;
        b >>= 1;
    }
    return sum;
}
int main()
{
    while(~scanf("%lld%lld%lld",&p,&a,&b))
    {
        if(a % p == 0)
        {
            printf("no solution\n");
            continue;
        }
        mp.clear();
        m = ceil(sqrt(p));
        flag = false;
        now = b % p;
        mp[now] = 0;
        for(int i = 1;i <= m;i++)
        {
            now = (now * a) % p;
            mp[now] = i;
        }
        t = qpow(a,m);
        now = 1;
        duke(i,1,m)
        {
            now = (now * t) % p;
            if(mp[now])
            {
                flag = true;
                ans = i * m - mp[now];
                printf("%lld\n",(ans % p + p) % p);
                break;
            }
        }
        if(!flag)
        printf("no solution\n");
    }
    return 0;
}

 

posted @ 2018-11-13 22:38  DukeLv  阅读(163)  评论(0编辑  收藏  举报