bzoj 1420&&bzoj 1319: Discrete Root 原根+BSGS+exgcd+模线性方程
来源:互联网 发布:ubuntu输入法 编辑:程序博客网 时间:2024/05/16 17:13
题意
已知k,a,p,求x ^ k=a (mod p)的所有根(根的范围[0,p-1])
分析
一开始看成是一道裸的BSGS,后来发现不是,然后就没思路了。
p是素数!!!
话说原根真的超级强大。我们先找到p的原根g,然后设
那么可以得到
根据原根的周期性,我们可以得到
然后直接上模线性方程就好了:
ax = b(mod n)
其实方程等价于 ax - ny = b, 标准模线性方程,但是得考虑剩余系。
算法导论上有两个定理:
定理一:设d = gcd(a, n), 假定对整数x’, y’, 有d = ax’ + ny’, 如果d | b, 则方程ax = b(mod)有一个解的值为x0, 满足:、
x0 = x’(b / d)(mod n)
定理二:假设方程ax = b(mod n)有解, x0是方程的任意一个解, 则方程对模n恰有d个不同的解, 分别为: xi = x0 + i * (n / d), 其中 i = 1,2,3……d - 1
有了这两个定理, 解方程就不难了。
还有这题细节比较多:
1、p=2和p=3没有原根,特判。
2、a=0特判。因为没有解。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<map>#include<cmath>using namespace std;typedef long long LL;const int N=1000005;LL a,k,p,g,ans[N],sta[N],top,tot;map<LL,LL> w;LL ksm(LL x,LL y,LL p){ LL ans=1; while (y) { if (y&1) ans=ans*x%p; x=x*x%p;y>>=1; } return ans;}LL get_g(LL n){ LL x=n-1; for (LL i=2;i<=n&&x>1;i++) if (x%i==0) { sta[++top]=i; while (x%i==0) x/=i; } for (LL g=2;;g++) { int i; for (i=1;i<=top;i++) if (ksm(g,(n-1)/sta[i],n)==1) break; if (i==top+1) return g; }}LL BSGS(LL a,LL p){ LL m=sqrt(p),ny=ksm(g,p-2,p),now=a; w[a]=p; for (LL i=1;i<m;i++) { now=now*ny%p; if (!w[now]) w[now]=i; } ny=ksm(g,m,p);now=1; for (int i=0;i<=m;i++) { if (w[now]) return (w[now]+(LL)i*m)%p; now=now*ny%p; }}LL gcd(LL x,LL y){ if (!y) return x; else return gcd(y,x%y);}void exgcd(LL a,LL b,LL &x,LL &y){ if (!b) { x=1;y=0; return; } exgcd(b,a%b,x,y); LL tmp=x; x=y; y=tmp-(a/b)*y;}int main(){ scanf("%lld%lld%lld",&p,&k,&a); if (!a) { putchar('0');return 0; } if(p==2) { if(a==1) puts("1\n1"); else puts("1\n0"); return 0; } if(p==3){ for(int i=0;i<=2;i++) if(ksm(i,k,p)==a) tot++; printf("%lld\n",tot); for(int i=0;i<=2;i++) if(ksm(i,k,p)==a) printf("%d\n",i); return 0; } g=get_g(p); LL z=BSGS(a,p); LL d=gcd(k,p-1); if (z%d!=0) { putchar('0'); return 0; } LL tmp=(p-1)/d,x,y; exgcd(k,p-1,x,y); x=x*(z/d);x=(x%(p-1)+p-1)%(p-1); for (int i=0;i<d;i++) ans[++tot]=ksm(g,x,p),x+=tmp; sort(ans+1,ans+tot+1); cout<<tot<<endl; for (int i=1;i<=tot;i++) printf("%lld\n",ans[i]); return 0;}
阅读全文
0 0
- bzoj 1420&&bzoj 1319: Discrete Root 原根+BSGS+exgcd+模线性方程
- [原根 指标 模方程 BSGS] BZOJ 1420 Discrete Root & BZOJ 1319 Sgu261Discrete Roots
- BZOJ 3239 Discrete Logging BSGS
- bzoj 3239: Discrete Logging BSGS
- BZOJ 3239 Discrete Logging BSGS
- bzoj1420 Discrete Root 原根 大步小步 exgcd
- Bzoj 3122 [Sdoi2013]随机数生成器(BSGS+exgcd)
- 【BZOJ】【P3239】【Discrete Logging】【题解】【BSGS】
- bzoj 3239: Discrete Logging (BSGS)
- bzoj1319&1420 Sgu261 Discrete Roots (原根+BSGS)
- BZOJ 1420&&BZOJ 1319 Discrete Roots 数论
- BZOJ 2242 [SDOI2011]计算器 BSGS+快速幂+EXGCD
- POJ 2417/BZOJ 3239(Discrete Logging-BSGS)[Template:数论]
- 【bzoj 3239】【POJ 2417】Discrete Logging(BSGS)
- BZOJ-2995&&2480&&3239 同余方程&Mod&Discrete Logging 拓展BSGS算法
- bzoj 1407 exgcd
- BZOJ 1407 exgcd
- bzoj 1477 exgcd
- keepalived+lvs部署中遇到的自动更改负载权重的问题
- 写代码后的学习与总结
- 朱自清的《匆匆》有感--时间有限,梦想很远,我们不能停下脚步
- IDEA java doc 接口文档输出
- 电表_正向有功、反向无功
- bzoj 1420&&bzoj 1319: Discrete Root 原根+BSGS+exgcd+模线性方程
- bootstrap+jquery 点击显示大图功能
- spring boot学习6之mybatis+PageHelper分页插件+jta多数据源事务整合
- highlight 动态添加代码,样式失效
- 算法提高 题目 3 函数求值
- spring MVC
- Linux_正则表达式(1.基础正则表达式)
- 英语阅读之二
- socket系列(二)——Javaee实现实时通信