[数论]原根与指标,BSGS
刚学了这方面的知识,总结一下。推荐学习数论方面的知识还是看书学习,蒟蒻看的是《初等数论》学的。
这里也推荐几个总结性质的博客,学习大佬的代码和习题。
原根:https://blog.csdn.net/fuyukai/article/details/50894609
BSGS:https://www.cnblogs.com/cjyyb/p/8810050.html
https://blog.csdn.net/sodacoco/article/details/81515576
然后也没什么好说的啦,以下是模板代码:
求一个数的最小原根:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL prm[],tot,N,root; LL Power(LL x,LL p,LL MOD) {
LL ret=;
for (;p;p>>=) {
if (p&) ret=(ret*x)%MOD;
x=(x*x)%MOD;
}
return ret;
} LL GetRoot(LL n) {
LL tmp=n-,tot=;
for (LL i=;i<=sqrt(tmp);i++) {
if(tmp%i==) {
prm[++tot]=i;
while(tmp%i==) tmp/=i;
}
}
if (tmp!=) prm[++tot] = tmp; //质因数分解
for (LL g=;g<=n-;g++) {
bool flag = ;
for(int i=;i<=tot;i++) //检测是否符合条件
if(Power(g,(n-)/prm[i],n)==) { flag=; break; }
if (flag)return g;
}
return ; //无解
} int main() {
cin >> N;
cout<<GetRoot(N)<<endl;
return ;
}
普通BSGS:计算a^x≡b(mod p),要求a和p互质。
#include<bits/stdc++.h>
#define MOD 76543 //这是哈希表大小
using namespace std; int hs[MOD],head[MOD],nxt[MOD],id[MOD],top;
void insert(int x,int y) {
int k=x%MOD;
hs[top]= x,id[top]=y,nxt[top]=head[k],head[k]=top++;
} int find(int x) {
int k=x%MOD;
for(int i=head[k];i!=-;i=nxt[i])
if(hs[i]==x) return id[i];
return -;
} //普通BSGS:计算A^X=B(mod C)求X(A和C互质)
int BSGS(int a,int b,int c) {
top=; memset(head,-,sizeof(head)); //清空哈希表
a%=c; b%=c; //先取模
if(b==) return ;
int m=sqrt(c*1.0),j;
long long x=,p=;
for(int i=;i<m;++i,p=p*a%c)
insert(p*b%c,i);//小步:存的是(a^j*b, j)
for(long long i=m;;i+=m) {
if((j=find(x=x*p%c))!=-) return i-j; //大步:a^(ms-j)=b(mod c)
if(i>c) break;
}
return -; //无解
} int main()
{
int a,b,c; cin>>a>>b>>c;
cout<<BSGS(a,b,c)<<endl;
return ;
}
拓展BSGS,计算a^x≡b(mod p),但不要求a和p互质。代码学习yyb大佬的,测试:SPOJ-MOD 。
#include<bits/stdc++.h>
#define MOD 76543 //这是哈希表大小
using namespace std;
typedef long long LL; LL power(LL x,LL p,LL mod) {
LL ret=;
for (;p;p>>=) {
if (p&) ret=(ret*x)%mod;
x=(x*x)%mod;
}
return ret;
} int hs[MOD],head[MOD],nxt[MOD],id[MOD],top;
void insert(int x,int y) {
int k=x%MOD;
hs[top]= x,id[top]=y,nxt[top]=head[k],head[k]=top++;
} int find(int x) {
int k=x%MOD;
for(int i=head[k];i!=-;i=nxt[i])
if(hs[i]==x) return id[i];
return -;
} //拓展BSGS:计算A^X=B(mod C)求X(不要求A,C互质)
int exBSGS(int y,int z,int p) {
y%=p; z%=p;
if (z==) return ;
int k=,a=;
while() { //消因子
int d=__gcd(y,p); if(d==)break;
if(z%d) return -; //无解
z/=d; p/=d; ++k; a=1LL*a*y/d%p;
if(z==a) return k;
}
top=; memset(head,-,sizeof(head)); //清空哈希表,BSGS
int m=sqrt(p)+;
for(int i=,t=z;i<m;++i,t=1LL*t*y%p) insert(t,i);
for(int i=,tt=power(y,m,p),t=1LL*a*tt%p;i<=m;++i,t=1LL*t*tt%p) {
int B=find(t); if(B==-) continue;
return i*m-B+k;
}
return -;
} int main()
{
int a,b,c;
while (scanf("%d%d%d",&a,&c,&b)==) {
if (a== && b== && c==) break;
int t=exBSGS(a,b,c);
if (t==-) puts("No Solution"); else printf("%d\n",t);
}
return ;
}
题目练习:
洛谷P2485
简单题,分别是求快速幂,逆元,BSGS。
#include<bits/stdc++.h>
#define MOD 76543 //这是哈希表大小
using namespace std;
typedef long long LL; LL power(LL x,LL p,LL mod) {
LL ret=;
for (;p;p>>=) {
if (p&) ret=(ret*x)%mod;
x=(x*x)%mod;
}
return ret;
} int hs[MOD],head[MOD],nxt[MOD],id[MOD],top;
void insert(int x,int y) {
int k=x%MOD;
hs[top]= x,id[top]=y,nxt[top]=head[k],head[k]=top++;
} int find(int x) {
int k=x%MOD;
for(int i=head[k];i!=-;i=nxt[i])
if(hs[i]==x) return id[i];
return -;
} //普通BSGS:计算A^X=B(mod C)求X(A和C互质)
int BSGS(int a,int b,int c) {
top=; memset(head,-,sizeof(head)); //清空哈希表
a%=c; b%=c; //先取模
if(b==) return ;
int m=sqrt(c*1.0),j;
long long x=,p=;
for(int i=;i<m;++i,p=p*a%c)
insert(p*b%c,i);//小步:存的是(a^j*b, j)
for(long long i=m;;i+=m) {
if((j=find(x=x*p%c))!=-) return i-j; //大步:a^(ms-j)=b(mod c)
if(i>c) break;
}
return -; //无解
} int main()
{
int T,k; cin>>T>>k;
while (T--) {
int y,z,p; scanf("%d%d%d",&y,&z,&p);
if (k==) printf("%lld\n",power(y,z,p));
if (k==) {
if (y%p==) puts("Orz, I cannot find x!");
else printf("%lld\n",z%p*power(y,p-,p)%p);
}
if (k==) {
if (y%p==) {puts("Orz, I cannot find x!"); continue;}
int t=BSGS(y,z,p);
if (t==-) puts("Orz, I cannot find x!");
else printf("%d\n",t);
}
}
return ;
}
洛谷P3306
完全不会做qwq,蒟蒻只能自闭半天之后看题解,跟着大佬推。这道题很好,细节也很多,值得多思考。
#include<bits/stdc++.h>
#define MOD 76543 //这是哈希表大小
using namespace std;
typedef long long LL; LL power(LL x,LL p,LL mod) {
LL ret=;
for (;p;p>>=) {
if (p&) ret=(ret*x)%mod;
x=(x*x)%mod;
}
return ret;
} int hs[MOD],head[MOD],nxt[MOD],id[MOD],top;
void insert(int x,int y) {
int k=x%MOD;
hs[top]= x,id[top]=y,nxt[top]=head[k],head[k]=top++;
} int find(int x) {
int k=x%MOD;
for(int i=head[k];i!=-;i=nxt[i])
if(hs[i]==x) return id[i];
return -;
} //普通BSGS:计算A^X=B(mod C)求X(A和C互质)
LL BSGS(int a,int b,int c) {
top=; memset(head,-,sizeof(head)); //清空哈希表
a%=c; b%=c; //先取模
if(b==) return ;
int m=sqrt(c*1.0),j;
long long x=,p=;
for(int i=;i<m;++i,p=p*a%c)
insert(p*b%c,i);//小步:存的是(a^j*b, j)
for(long long i=m;;i+=m) {
if((j=find(x=x*p%c))!=-) return i-j; //大步:a^(ms-j)=b(mod c)
if(i>c) break;
}
return -; //无解
} int main()
{
int T; cin>>T;
LL p,a,b,x1,t;
while (T--) {
scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t);
if (x1==t) { puts(""); continue; }
if (a==) {
if (b==t) puts(""); else puts("-1");
continue;
}
if (a==) {
if (b==) puts("-1");
else printf("%lld\n",((t-x1)%p+p)%p*power(b,p-,p)%p+);
continue;
}
int tmp=(t-t*a)%p; tmp=(tmp+p)%p;
tmp-=b; tmp%=p; tmp=(tmp+p)%p;
int ttmp=(x1-x1*a)%p; ttmp=(ttmp+p)%p;
ttmp-=b; ttmp%=p; ttmp=(ttmp+p)%p;
tmp=tmp*power(ttmp,p-,p)%p; printf("%lld\n",BSGS(a,tmp,p)+);
}
return ;
}
BZOJ 1319
[数论]原根与指标,BSGS的更多相关文章
- 数论算法 剩余系相关 学习笔记 (基础回顾,(ex)CRT,(ex)lucas,(ex)BSGS,原根与指标入门,高次剩余,Miller_Rabin+Pollard_Rho)
注:转载本文须标明出处. 原文链接https://www.cnblogs.com/zhouzhendong/p/Number-theory.html 数论算法 剩余系相关 学习笔记 (基础回顾,(ex ...
- 求同余方程x^A=B(mod m)的解个数(原根与指标)
求方程:的解个数 分析:设,那么上述方程解的个数就与同余方程组:的解等价. 设同于方程的解分别是:,那么原方程的解的个数就是 所以现在的关键问题是求方程:的解个数. 这个方程我们需要分3类讨论: 第一 ...
- uoj86 mx的组合数 (lucas定理+数位dp+原根与指标+NTT)
uoj86 mx的组合数 (lucas定理+数位dp+原根与指标+NTT) uoj 题目描述自己看去吧( 题解时间 首先看到 $ p $ 这么小还是质数,第一时间想到 $ lucas $ 定理. 注意 ...
- BZOJ2219数论之神——BSGS+中国剩余定理+原根与指标+欧拉定理+exgcd
题目描述 在ACM_DIY群中,有一位叫做“傻崽”的同学由于在数论方面造诣很高,被称为数轮之神!对于任何数论问题,他都能瞬间秒杀!一天他在群里面问了一个神题: 对于给定的3个非负整数 A,B,K 求出 ...
- 【bzoj2219-数论之神】求解x^a==b(%n)-crt推论-原根-指标-BSGS
http://www.lydsy.com/JudgeOnline/problem.php?id=2219 弄了一个晚上加一个午休再加下午一个钟..终于ac..TAT 数论渣渣求轻虐!! 题意:求解 x ...
- BZOJ1319Sgu261Discrete Roots——BSGS+exgcd+原根与指标+欧拉定理
题目描述 给出三个整数p,k,a,其中p为质数,求出所有满足x^k=a (mod p),0<=x<=p-1的x. 输入 三个整数p,k,a. 输出 第一行一个整数,表示符合条件的x的个数. ...
- 51Nod1039 N^3 Mod P 数论 原根 BSGS
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1039.html 题目传送门 - 51Nod1039 题意 题解 这题我用求高次剩余的做法,要卡常数. ...
- 51Nod1038 X^A Mod P 数论 原根 BSGS
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1038.html 题目传送门 - 51Nod1038 题意 题解 在模质数意义下,求高次剩余,模板题. ...
- [UOJ86]mx的组合数——NTT+数位DP+原根与指标+卢卡斯定理
题目链接: [UOJ86]mx的组合数 题目大意:给出四个数$p,n,l,r$,对于$\forall 0\le a\le p-1$,求$l\le x\le r,C_{x}^{n}\%p=a$的$x$的 ...
随机推荐
- APP稳定性测试-monkey执行
Monkey命令行可用的全部选项 *示例 : adb shell monkey -p cn.lejiayuan.alpha --pct-touch 30 --pct-motion 15 --pct-t ...
- BZOJ 3879: SvT 虚树 + 后缀自动机
Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...
- 【前端技术】一篇文章搞掂:uni-app
语法 //列表遍历,遍历数组,第一个参数为数组中元素,可以给第二个参数作为索引值 <view v-for="(item, itemIndex) in card" :key=& ...
- php 中 http_build_query用法
http_build_query (PHP 5) http_build_query -- 生成 url-encoded 之后的请求字符串描述string http_build_query ( arra ...
- P1058立体图(面对代码解释)
传送 样例: 输出样例: (洛谷上面的那个太丑了就不放了) 大佬博客在此 乍一看好像真的没有什么思路 所以我们结合ybr大佬的代码进行分析 疑点都将在代码下面进行分析(面对代码做题模式开始) #inc ...
- :nth-child 与 ;nth-of-child
//:nth-child:是选择父元素下的第几个元素,不分标签类别,计数从1开始 //:nth-of-type:是选择父元素下的同类型元素的第几个元素.区分标签类别,计数从1开始
- Jenkins使用四:Jenkins创建任务,实现代码有改动时,自动构建
新建任务 指定在哪台节点运行 添加要监控的git地址和使用账号,此账号为设置节点时配置公私钥时设置的ssh登录账号 设置检查代码是否有变更的频率,每三分钟检查一次,如果检查到有变更就构建 修改文件再提 ...
- Delphi 文件转换Base64
uses EncdDecd; function FileToBase64(FileName: string): string; var MemoryStream: TMemoryStream;beg ...
- Selenium WebDriver 常用API
public class Demo1 { WebDriver driver; @BeforeMethod public void visit(){ //webdriver对象的声明 System.se ...
- 页面跳转(包括vue路由)
1.JS实现页面跳转 1.1 使用window.location的href属性跳转 window.location.href = 'http://www.baidu.com';此处window可以省略 ...