【EXT-BSGS算法求离散对数】POJ Clever Y 3243

Clever Y

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 7259 Accepted: 1795

Description

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

XY mod Z = K

Given X, Y,
Z
, we all know how to figure out K fast. However, given X,Z,K, 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 integersX,Z,
K (0 ≤ X, Z, K ≤ 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 feasibleY (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

POJ Monthly--2007.07.08, Guo, Huayang

题意:

X^Y%Z=K,计算等式成立的最小的Y值。

解题思路:

扩展BSGS算法,普通BSGS算法要求 A^x≡B( mod C )的C值为质数,因为等式有解的要求是GCD(A,C)|B,只有当C为质数,才一定成立。而此题并没有说C一定为质数。所以就要用到EXT-BSGS算法,看这个算法也是理解了好久。网上参考讲解这个算法的不多,找资料都找好久。自己总结下这个算法。

首先必须要会普通的BSGS,普通BSGS算法讲解:点击打开链接

我们知道,普通的BSGS算法可以处理C为质数的情况,也就是保证GCD(A,C)|B,所以我们只要保证出现这种情况即可。怎么才能出现这种情况?我们可以让GCD(A,C)=1,这样就能保证它一定能被B整除。

如何能让(A,C)=1?我们可以一直让C,除以(A,C)。当C把所有的A,C的公约数除尽之后,(A,C)一定等于1。注意,再求(A,C)时,C值是变换后的C值,即C[i]=C[i] / ( A,C[i-1] )。

为了保证等式成立,我们必须用等式的每部分都除以这个值。我们一直循环C/(A,C),B/(A,C),而A^x的值不是A/(A,C)这点要注意。除的时候我们考虑的是从A^x次方中取出一个A除以(A,C),这时:A^x=A/(A,C)*A^(x-1)。

我们的循环操作截止到(A,C)=1,所以在经过cnt次的操作后A^x=D*A^(x-cnt),因为我们总共取出cnt个A。我们每次循环还要更新D值,就是每次A/(A,C)的值乘以上次循环的值。即循环的是:D=D*A/(A,C)。所以我们这里D≠A^cnt。这点要注意一下。

我们经过上述操作之后等式变成 D*A^(x′)≡B′ ( mod C′ ),x′=x-cnt。此时 只要我们求解出这个等式的解x′,就能求出x的值,x=x′+cnt。因为A*D≡B*D( mod C*D )等价于A≡B( mod C )。所以我们求得的解是等价的。

而且在这里面我们(A,C)=1,这时我们就可以直接利用普通BSGS求解。

等价为 A^(i*M)*D*A^j≡B( mod C )。我们查找合适的j值就可以了。

最后我们还有一个重要的的问题没解决,我们看一个例子:49^x≡0( mod 343),很显然x=0,但是如果根据我们上述方法得出的结果就会是2。这里答案就显然变得不对,这里我们会发现答案如果本身小于cnt,再加上cnt的话就会变成一个不正确的值,所以我们可以尝试枚举一下所有小于cnt的x值,看下x值是否存在。如果存在的话直接返回x值即可,不用再进行BSGS步骤了。因为C每次最小消去的因子是2,所以cnt最大是log(C),我们枚举[0,log(C)]值就可以了。

AC代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>

using namespace std;

const int MAXN = 1000010;
typedef long long LL;

bool hash[MAXN];
LL p[MAXN];
LL var[MAXN];

void insert_x(LL n,LL v)
{
    int x=v%MAXN;
    while(hash[x]&&var[x]!=v){
        x++;
        if(x==MAXN)
            x=0;
    }
    if(!hash[x]){
        p[x]=n;
        var[x]=v;
        hash[x]=true;
    }
}

LL find_x(LL v)
{
    int x=v%MAXN;
    while(hash[x]&&var[x]!=v){
        x++;
        if(x==MAXN)
            x=0;
    }
    if(hash[x]) return p[x];
    return -1;
}

LL gcd(LL a,LL b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}

LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0){
        x=1;y=0;
        return a;
    }
    LL r=exgcd(b,a%b,x,y);
    LL t=x;
    x=y;
    y=t-a/b*y;
    return r;
}

LL BSGS(LL A,LL B,LL C)
{
    LL n=1;
    for(int i=0;i<110;i++){//枚举所有小于log(C)的x值
        if(n==B%C) return i;
        n=n*A%C;
    }
    int cnt=0;
    LL res=1;
    LL divisor=gcd(A,C);
    while(divisor!=1){ //消去(A,C)的所有公约数
        if(B%divisor){
            return -1;
        }
        C/=divisor;
        B/=divisor;
        res=res*A/divisor%C;
        divisor=gcd(A,C);
        cnt++;
    }
    LL M=ceil(sqrt(C*1.0));
    LL temp=1;
    for(int i=0;i<M;i++){
        insert_x(i,temp);
        temp=temp*A%C;
    }
    for(int i=0;i<M;i++){
        LL x,y;
        LL r=exgcd(res,C,x,y);
        x=x*B;
        x=(x%C+C)%C;
        LL coordinate=find_x(x);
        if(coordinate!=-1){
            return (i*M+coordinate+cnt);
        }
        res=res*temp%C;
    }
    return -1;
}

int main()
{
    LL X,Z,K;
    while(scanf("%lld%lld%lld",&X,&Z,&K)!=EOF){
        if(!X&&!Z&&!K)break;
        memset(hash,false,sizeof(hash));
        memset(var,-1,sizeof(var));
        memset(p,-1,sizeof(p));
        LL coordinate=BSGS(X,K,Z);
        if(coordinate==-1) printf("No Solution\n");
        else printf("%lld\n",coordinate);
    }
    return 0;
}

版权声明:本文为博主原创文章,转载请注明出处。

时间: 2024-08-26 11:20:24

【EXT-BSGS算法求离散对数】POJ Clever Y 3243的相关文章

Clever Y POJ - 3243 (扩展BSGS)

Clever Y POJ - 3243 题意:给a,c,b,求最小的x使得 ax≡b (mod c). 扩展BSGS算法~ 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #define ll long long 6 using namespace std; 7 const int mod=99991; 8 ll head[mod],nex

POJ 3243 Clever Y BSGS

Clever Y Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6861   Accepted: 1676 Description Little Y finds there is a very interesting formula in mathematics: XY mod Z = K Given X, Y, Z, we all know how to figure out K fast. However, give

BSGS算法+逆元 POJ 2417 Discrete Logging

POJ 2417 Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4860   Accepted: 2211 Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarith

【POJ】3243 Clever Y

http://poj.org/problem?id=3243 题意:求$a^y \equiv b \pmod{p}$最小的$y$.(0<=x, y, p<=10^9) #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <iostream> typedef long long ll; using namespace st

【POJ 2195】 Going Home(KM算法求最小权匹配)

[POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20303   Accepted: 10297 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit ste

poj 3243 Clever Y 高次方程

1 Accepted 8508K 579MS C++ 2237B/** 2 hash的强大,,还是高次方程,不过要求n不一定是素数 3 **/ 4 #include <iostream> 5 #include <cstdio> 6 #include <cmath> 7 #include <cstring> 8 #include <algorithm> 9 using namespace std; 10 long long a,b,n; 11 co

[POJ 1273]Drainage Ditches(Edmond-Krap算法和Dinic算法求最大流)

自NOIP 2014结束之后将近一个星期没撸题了,现在开始搞省选,发个水水的裸网络流题解吧. 题目链接:http://poj.org/problem?id=1273 裸网络流,模板题. 1.Edmond_Karp算法 #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <que

BSGS算法及拓展

https://www.zybuluo.com/ysner/note/1299836 定义 一种用来求解高次同余方程的算法. 一般问题形式:求使得\(y^x\equiv z(mod\ p)\)的最小非负\(x\). \(BSGS\)算法 要求\(p\)是质数. 由费马小定理可知,\(y^{p-1}\equiv1(mod\ p)\),所以暴力枚举只要枚举到\(p?1\)即可. 但是由于\(p\)一般都很大,所以一般都跑不动... 优化算法\(ing...\) 现在令\(x=mi?j\)(其中\(m

Tarjan算法各种&amp;RMQ&amp; POJ 3694

关于tarjan 的思想可以在网上搜到,具体我也不太清楚,应该说自己理解也不深,下面是做题经验得到的一些模板. 其中有很多转载,包括BYVoid等,感谢让我转...望各路大神愿谅 有向图求连通分量的一般方法: 1 void Tarjan(u) { 2 dfn[u]=low[u]=++index 3 stack.push(u) 4 for each (u, v) in E { 5 if (v is not visted) { 6 tarjan(v) 7 low[u] = min(low[u], l