bzoj1319&1420 Sgu261 Discrete Roots (原根+BSGS)
来源:互联网 发布:编程培训机构 编辑:程序博客网 时间:2024/06/05 15:40
bzoj1319&1420 Sgu261 Discrete Roots
原题地址:
http://www.lydsy.com/JudgeOnline/problem.php?id=1319
http://www.lydsy.com/JudgeOnline/problem.php?id=1420
题意:
给出三个整数p,k,a,其中p为质数,求出所有满足x^k=a (mod p),0<=x<=p-1的x。
数据范围
0 < = a < p < = 10^9, 2 < = k < = 100000
题解:
由于p为质数,可以求出p的原根。
1.a=0:
那么x只能为p的倍数,又因为0<=x<=p-1,则只有一个解 0。
2.a!=0:
因为p为质数,a与p互素,则a可以用
同时,x也与p互素。
由
得
由于
所以上述
快速幂一下得到每个x。
代码:
#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<algorithm>#define LL long longusing namespace std;const int N=100005;const LL S=100003;LL k,a,p,phi,g,inda,indx,top;LL stack[N];LL modpow(LL A,LL B,LL mod){ LL base=A; LL ans=1LL; for(;B;B>>=1) { if(B&1) ans=(ans*base)%mod; base=(base*base)%mod; } return ans;}struct H{ LL head[S],dest[S][2]; int nxt[N],num; void init() {memset(head,0,sizeof(head)); num=0;} void insert(LL A,LL B) { LL key=B%S; for(int i=head[key];i;i=nxt[i]) if(dest[i][1]==B) return; num++; dest[num][0]=A; dest[num][1]=B; nxt[num]=head[key]; head[key]=num; } LL find(LL val) { LL key=val%S; for(int i=head[key];i;i=nxt[i]) if(dest[i][1]==val) return dest[i][0]; return -1; }}Hash;LL BSGS(LL A,LL B,LL P){ Hash.init(); LL cur=1; LL C=sqrt(P-1)+1; for(LL i=0;i<C;i++) { if(cur==B) return i; Hash.insert(i,cur); cur=cur*A%P; } LL base=modpow(cur,P-2,P); cur=B*base%P; for(LL i=C;i<P;i=i+C) { LL ret=Hash.find(cur); if(ret!=-1) return ret+i; cur=cur*base%P; } return -1;}LL getG(LL m){ LL x=phi; top=0; for(LL i=2;i*i<=x;i++) { if(x%i==0) { stack[++top]=i; while(x%i==0) x=x/i; } } if(x>1) stack[++top]=x; for(LL i=1;i<=m;i++) { int j; for(j=1;j<=top;j++) if(modpow(i,phi/stack[j],m)==1) break; if(j>top) return i; } return -1;}LL getgcd(LL A,LL B) {return B==0? A: getgcd(B,A%B);}void exgcd(LL A,LL B,LL &x,LL &y){ if(B==0) { x=1; y=0; return;} LL x0,y0; exgcd(B,A%B,x0,y0); x=y0; y=x0-(A/B)*y0;}int main(){ scanf("%lld%lld%lld",&p,&k,&a); phi=p-1; if(a==0) { printf("1\n0\n"); return 0;} g=getG(p); inda=BSGS(g,a,p); LL gcd=getgcd(k,p-1); if(inda%gcd!=0) { printf("0\n"); return 0;} LL A=k/gcd; LL B=(p-1)/gcd; LL x,y; exgcd(A,B,x,y); x=(x+B)%B; x=(x*(inda/gcd)+B)%B; top=0; for(;x<p-1;x+=B) stack[++top]=modpow(g,x,p); sort(stack+1,stack+top+1); printf("%lld\n",top); for(int i=1;i<=top;i++) printf("%lld\n",stack[i]); return 0;}
补充:
为什么
一般化:
因为
所以解的个数为
阅读全文
0 0
- bzoj1319&1420 Sgu261 Discrete Roots (原根+BSGS)
- sgu261:Discrete Roots(原根+离散对数+扩展欧几里得)
- [原根 指标 模方程 BSGS] BZOJ 1420 Discrete Root & BZOJ 1319 Sgu261Discrete Roots
- bzoj 1420&&bzoj 1319: Discrete Root 原根+BSGS+exgcd+模线性方程
- SGU 261 Discrete Roots(原根+高次同余方程+线性同余方程)
- bzoj1420&bzoj1319 Discrete Root
- [BZOJ3239][poj2417]Discrete Logging(BSGS算法)
- POJ 2417 Discrete Logging (BSGS)
- bzoj 3239: Discrete Logging (BSGS)
- poj2417 bzoj3239 Discrete Logging(bsgs)
- Discrete Roots
- BZOJ 1420&&BZOJ 1319 Discrete Roots 数论
- [省选前题目整理][SGU 261]Discrete Roots(扩展欧几里得+中国剩余定理+原根+大步小步算法)
- BSGS+原根+离散对数
- 【bzoj3239】Discrete Logging BSGS
- [BZOJ3239][BSGS]Discrete Logging
- POJ 1284 Primitive Roots (原根)
- POJ1284 Primitive Roots(原根定理)
- 用rand()和srand()产生为随机数的方法总结
- 一个总的NOIP2017总结
- 求损失函数时候的最大似然估计
- 快速学会 Grid 布局
- codeforces896A Nephren gives a riddle (dfs)
- bzoj1319&1420 Sgu261 Discrete Roots (原根+BSGS)
- 北大ACM
- Qt中纯C++项目发布为dll的方法
- fan xing
- 「游戏引擎Mojoc」(8)C实现泛型ArrayList
- 多线程编程学习::POSIX 多线程基础(三)
- 设计模式-单例模式(Singleton Pattern)
- NIO学习一、NIO简介
- 排序之插入排序