BSGS及扩展BSGS模板

BSGS

#include <iostream>//poj2417
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long

using namespace std;
const int maxint=((1<<30)-1)*2+1;

int A,B,C;
struct Hashmap{
    static const int Ha=999917,maxe=46340;
    int E,lnk[Ha],son[maxe+5],nxt[maxe+5],w[maxe+5];
    int top,stk[maxe+5];
    void clear() {E=0;while(top) lnk[stk[top--]]=0;}
    void Add(int x,int y){son[++E]=y;nxt[E]=lnk[x];w[E]=maxint;lnk[x]=E;}
    bool count(int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return true;
        return false;
    }
    int& operator [] (int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return w[j];
        Add(x,y);stk[++top]=x;return w[E];
    }
};
Hashmap f;

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

int BSGS(int A,int B,int C)
{
    if(C==1) if(!B) return A!=1; else return -1;
    if(B==1) if(A) return 0; else return -1;
    if(A%C==0) if(!B) return 1;else return -1;
    int m=ceil(sqrt(C)),D=1,Base=1;f.clear();
    for(int i=0;i<=m-1;i++)//先把A^j存进哈希表
    {
        f[Base]=min(f[Base],i);
        Base=((ll)Base*A)%C;
    }
    for(int i=0;i<=m-1;i++)
    {
        int x,y,r=exgcd(D,C,x,y);
        x=((ll)x*B%C+C)%C;//扩欧求A^j
        if(f.count(x)) return i*m+f[x];//找到解
        D=((ll)D*Base)%C;
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d%d",&C,&A,&B))
    {
        int ans=BSGS(A,B,C);
        if(ans==-1) printf("no solution\n");
        else printf("%d\n",ans);
    }
    return 0;
}

扩展BSGS

#include <iostream>//poj3243
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long

using namespace std;
const int maxint=((1<<30)-1)*2+1;

int A,B,C;
struct Hashmap{
    static const int Ha=999917,maxe=46340;
    int E,lnk[Ha],son[maxe+5],nxt[maxe+5],w[maxe+5];
    int top,stk[maxe+5];
    void clear() {E=0;while(top) lnk[stk[top--]]=0;}
    void Add(int x,int y){son[++E]=y;nxt[E]=lnk[x];w[E]=maxint;lnk[x]=E;}
    bool count(int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return true;
        return false;
    }
    int& operator [] (int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return w[j];
        Add(x,y);stk[++top]=x;return w[E];
    }
};
Hashmap f;

int gcd(int a,int b){
    if(!b) return a;
    else return gcd(b,a%b);
}

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

int exBSGS(int A,int B,int C)
{
    if(C==1) if(!B) return A!=1;else return -1;
    if(B==1) if(A) return 0;else return -1;
    if(A%C==0) if(!B) return 1;else return -1;
    int r,D=1,num=0;
    while((r=gcd(A,C))>1)
    {
        if(B%r) return -1;num++;
        B/=r;C/=r;D=((ll)D*A/r)%C;
    }
    for(int i=0,now=1;i<num;i++,now=((ll)now*A)%C)
    {
        if(now==B) return i;
    }
    int m=ceil(sqrt(C)),Base=1;f.clear();
    for(int i=0;i<=m-1;i++)
    {
        f[Base]=min(f[Base],i);
        Base=((ll)Base*A)%C;
    }
    for(int i=0;i<=m-1;i++)
    {
        int x,y,r=exgcd(D,C,x,y);
        x=((ll)x*B%C+C)%C;
        if(f.count(x)) return i*m+f[x]+num;
        D=((ll)D*Base)%C;
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d%d",&A,&C,&B))//A^y mod C=B
    {
        if(!A&&!B&&!C) break;
        int ans=exBSGS(A,B,C);
        if(ans==-1) printf("No Solution\n");
        else printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Fy1999/p/9786240.html

时间: 2024-11-07 13:52:33

BSGS及扩展BSGS模板的相关文章

BSGS和扩展BSGS

BSGS: 求合法的\(x\)使得\(a ^ x \quad mod \quad p = b\) 先暴力预处理出\(a^0,a^1,a^2.....a^{\sqrt{p}}\) 然后把这些都存在map里 : \(map[a^x] = x\) 一个合法的x满足\(x = k\sqrt{p} + l\)使得\(a^x = b\),因此可以直接枚举k,于是有: \[a^x = a^{k\sqrt{p}} \cdot a^l = b\] \[a^l = \frac{b}{a^{k\sqrt{p}}} =

bzoj 3283 扩展BSGS + 快速阶乘

T2  扩展BSGS T3 快速阶乘 给定整数n,质数p和正整数c,求整数s和b,满足n! / pb = s mod pc 考虑每次取出floor(n/p)个p因子,然后将问题转化为子问题. 1 /************************************************************** 2 Problem: 3283 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:1704 ms 7 Memor

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

http://poj.org/problem?id=3243 这道题的输入数据输入后需要将a和b都%p https://blog.csdn.net/zzkksunboy/article/details/73162229 在大约sqrt( p )的复杂度求出 ( a^x ) % p = b % p中的x 扩展bsgs增加了对p不是素数的情况的处理. 扩展bsgs在处理过a,b,p之后进行bsgs的时候x处理不到num以下的部分,这部分在处理a,b,p的时候处理过了(b=1输出num)所以不用考虑.

Codeforces 1106F Lunar New Year and a Recursive Sequence (数学、线性代数、线性递推、数论、BSGS、扩展欧几里得算法)

哎呀大水题..我写了一个多小时..好没救啊.. 数论板子X合一? 注意: 本文中变量名称区分大小写. 题意: 给一个\(n\)阶递推序列\(f_k=\prod^{n}_{i=1} f_{k-i}b_i\mod P\)其中\(P=998244353\), 输入\(b_1,b_2,...,b_n\)以及已知\(f_1,f_2,...,f_{n-1}=1\), 再给定一个数\(m\)和第\(m\)项的值\(f_m\), 求出一个合法的\(f_n\)值使得按照这个值递推出来的序列满足第\(m\)项的值为

扩展KMP模板

扩展KMP:    给出模板串A和子串B,长度分别为lenA和lenB,要求在线性时间内,对于每个A[i](0 <= i < lenA),求出A[i..lenA-1]与B的最长公共前缀长度,记为ex[i](或者说,ex[i]为满足A[i..i + z - 1]==B[0 .. z - 1]的最大的z值).    扩展KMP可以用来解决很多字符串问题,如求一个字符串的最长回文子串和最长重复子串.[算法]    设next[i]为满足B[i..i + z - 1] == B[0..z - 1]的最

ES6新语法之---对象字面量扩展、模板字符串(5)

这节课学习ES6中对象字面量扩展和新增模板字符串 第一部分:对象字面量扩展 1.简洁写法 ES6对于对象字面量属性提供了简写方式. 1.1:属性简写 //传统写法 var x = 2, y = 3, o = { x: x, y: y }; //ES6简洁写法 var x = 2, y = 3, o = { x, //属性名和赋值变量名相同时,可简写 y }; 1.2:方法简写 //传统写法 var o = { x: function() { //... }, y: function() { //

HDU 6153 A Secret(扩展KMP模板题)

A Secret Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others) Total Submission(s): 2523    Accepted Submission(s): 934 Problem Description Today is the birthday of SF,so VS gives two strings S1,S2 to SF as a present,w

扩展kmp 模板

#include<iostream> #include<string> using namespace std; const int MM=100005; int next[MM],extand[MM]; char S[MM],T[MM]; void GetNext(const char *T){ int len=strlen(T),a=0; next[0]=len; while(a<len-1 && T[a]==T[a+1]) a++; next[1]=a;