【BZOJ 1319】 Sgu261Discrete Rootsv (原根+BSGS+EXGCD)

1319: Sgu261Discrete Roots

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 389  Solved: 172

Description

给出三个整数p,k,a,其中p为质数,求出所有满足x^k=a (mod p),0<=x<=p-1的x。

Input

三个整数p,k,a。

Output

第一行一个整数,表示符合条件的x的个数。 第二行开始每行一个数,表示符合条件的x,按从小到大的顺序输出。

Sample Input

11 3 8

Sample Output

1
2

HINT

2<=p<p<=10^9
 2<=k<=100000,0<=a

【分析】

  

  终于发现原根的用处了!原根的幂构成模p的缩系,即用原根的幂可以表示所有模p下的数。假设模p下的一个原根是g,对于方程x^k=a(%prim) 可以写成(g^i)^k三g^j(%p),那么有g^j=三a(mod p),j可以用BSGS求得,那么i*k三j(%phi[p]),这个可以用exgcd求出所有可行的i,答案为g^i。

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 using namespace std;
  9 #define LL long long
 10 #define Maxn 1000010
 11
 12 LL ax,ay;
 13 LL exgcd(LL a,LL b)
 14 {
 15     if(b==0) {ax=1;ay=0;return a;}
 16     LL g=exgcd(b,a%b);
 17     LL xx=ax;
 18     ax=ay;ay=xx-(a/b)*ay;
 19     return g;
 20 }
 21
 22 LL np[Maxn];
 23 void div(LL x)
 24 {
 25     np[0]=0;
 26     for(LL i=2;i*i<=x;i++) if(x%i==0)
 27     {
 28         np[++np[0]]=i;
 29         while(x%i==0) x/=i;
 30     }
 31     if(x>1) np[++np[0]]=x;
 32 }
 33
 34 LL qpow(LL x,LL b,LL p)
 35 {
 36     LL xx=x,pp=p,ans=1;
 37     while(b)
 38     {
 39         if(b&1) ans=(ans*xx)%p;
 40         xx=(xx*xx)%p;
 41         b>>=1;
 42     }
 43     return (LL)ans;
 44 }
 45
 46 LL ffind(LL p)
 47 {
 48     div(p-1);
 49     for(LL i=2;i<p;i++)
 50     {
 51         bool ok=1;
 52         for(LL j=1;j<=np[0];j++)
 53         {
 54             if(qpow(i,(p-1)/np[j],p)==1) {ok=0;break;}
 55         }
 56         if(ok) return i;
 57     }
 58     return -1;
 59 }
 60
 61 LL cnt;
 62 struct node
 63 {
 64     LL id,val;
 65 }t[Maxn];
 66
 67 bool cmp(node x,node y) {return (x.val==y.val)?(x.id<y.id):(x.val<y.val);}
 68
 69 LL t_div(LL x)
 70 {
 71     LL l=0,r=cnt;
 72     while(l<r)
 73     {
 74         LL mid=(l+r)>>1;
 75         if(t[mid].val==x) return t[mid].id;
 76         if(t[mid].val>x) r=mid-1;
 77         else l=mid+1;
 78     }
 79     if(t[l].val==x) return t[l].id;
 80     return -1;
 81 }
 82
 83 LL BSGS(LL x,LL c,LL p)
 84 {
 85     t[0].id=0;t[0].val=1;
 86     LL sq=(LL)ceil(sqrt((double)p));
 87     for(LL i=1;i<=sq;i++) t[i].id=i,t[i].val=(t[i-1].val*x)%p;
 88     sort(t,t+1+sq,cmp);
 89     cnt=0;
 90     for(LL i=1;i<=sq;i++) if(t[i].val!=t[i-1].val) t[++cnt]=t[i];
 91
 92     LL bm=qpow(x,sq,p);
 93     bm=qpow(bm,p-2,p);
 94     LL tmp=c;
 95     for(LL i=0;i<=sq;i++)
 96     {
 97         LL now=t_div(tmp);
 98         if(now!=-1) return i*sq+now;
 99         tmp=(tmp*bm)%p;
100     }
101     return -1;
102 }
103
104 LL op[Maxn];
105
106 int main()
107 {
108     LL p,k,a;
109     scanf("%lld%lld%lld",&p,&k,&a);
110     LL g=ffind(p);
111     LL C=BSGS(g,a,p);
112     if(C==-1) {printf("0\n");return 0;}
113     C%=p-1;
114     LL d=exgcd(k,p-1);
115     if(C%d!=0) {printf("0\n");return 0;}
116     ax*=C/d;
117     ax=(ax%((p-1)/d)+((p-1)/d))%((p-1)/d);
118
119     LL ans=qpow(g,ax,p),id=ax,mx=ans,add=qpow(g,(p-1)/d,p);
120     op[0]=0;
121     op[++op[0]]=ans;
122     LL fs=ans;
123     while(add!=1)
124     {
125         id=ax+((p-1)/d);
126         ans=(ans*add)%p;
127         if(ans==fs) break;
128         op[++op[0]]=ans;
129     }
130     sort(op+1,op+1+op[0]);
131     printf("%lld\n",op[0]);
132     for(LL i=1;i<=op[0];i++) printf("%lld\n",op[i]);
133     return 0;
134 }

[BZOJ 1319]

2016-09-07 13:52:58

时间: 2024-10-11 02:08:19

【BZOJ 1319】 Sgu261Discrete Rootsv (原根+BSGS+EXGCD)的相关文章

BZOJ 2219 数论之神 BSGS+CRT

题意:链接 方法: BSGS+CRT 解析: 这道题有什么区别呢? 就是他取模的值不是一个质数了 这怎么办呢? 我们来把这个数分解质因数. P=∏piti 然后对于每一个piti我们单独计算. 最后用中国剩余定理合并 这其实跟想象中的中国剩余定理没有什么关系,其实是其中的一个性质,就是mod p的解数总数量等于每一个mod piti的乘积. 这是一个性质,别问我证明. 原方程xA=B(mod C) 转化为xA=B(mod Ci)?>Ci是质数或是质数的幂次. 我们可以单独计算. 这跟之前的题类似

CF1106F Lunar New Year and a Recursive Sequence(矩阵快速幂+bsgs+exgcd)

题面 传送门 前置芝士 \(BSGS\) 什么?你不会\(BSGS\)?百度啊 原根 对于素数\(p\)和自然数\(a\),如果满足\(a^x\equiv 1\pmod{p}\)的最小的\(x\)为\(p-1\),那么\(a\)就是\(p\)的一个原根 离散对数 对于素数\(p\),以及\(p\)的一个原根\(g\),定义\(y\)为\(x\)的离散对数,当且仅当\(g^y\equiv x\pmod{p}\),记\(y\)为\(ind_g x\).不难发现原数和离散对数可以一一对应.也不难发现离

Codeforces 536F Lunar New Year and a Recursive Sequence | BSGS/exgcd/矩阵乘法

我诈尸啦! 高三退役选手好不容易抛弃天利和金考卷打场CF,结果打得和shi一样--还因为queue太长而unrated了!一个学期不敲代码实在是忘干净了-- 没分该没分,考题还是要订正的 =v= 欢迎阅读本题解! P.S. 这几个算法我是一个也想不起来了 TAT 题目链接 Codeforces 536F Lunar New Year and a Recursive Sequence 新年和递推数列 题意描述 某数列\(\{f_i\}\)递推公式:\[f_i = (\prod_{j=1}^kf_{

BZOJ 3122 [Sdoi2013]随机数生成器 BSGS

题意:链接 方法: BSGS 解析: 首先他给出了你数列在mod p意义下的递推式. 所以我们可以求出来通项. Xn+1+k=a?(Xn+k) 所以b=(a?1)?k 则我们可以解出来k 那么这个数列的通项是什么呢? Xn=an?1?(X1+k)?k 题中给定Xn 求出n就行了. 所以只需要移项就好了. 这里有个问题,此时我们的通项公式是不包含首项的,所以需要特判首项,另外还有第一项以外为常数项的时候. 代码: #include <cmath> #include <cstdio>

BZOJ 2701&amp;&amp;BZOJ 1319 Discrete Roots 数论

题目大意:求方程xk≡a(mod p)在[0,p)区间内的全部解 取p的一个原根g,两侧取指标得到: k?indgx≡indga(mod p?1) 上EXGCD即可 注意a=0要特判 (EXGCD已死系列-- #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define INF 0x3f3f3f3f3f3

BZOJ 3239 Discrete Logging(BSGS)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3239 [题目大意] 计算满足 Y^x ≡ Z ( mod P) 的最小非负整数 [题解] BSGS裸题. [代码] #include <cstdio> #include <cmath> #include <map> #include <algorithm> #include <tr1/unordered_map> using name

bzoj2242: [SDOI2011]计算器 BSGS+exgcd

你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值:(快速幂) 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数:(exgcd) 3.给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数.(BSGS) /************************************************************** Problem: 2242 User: walfy Language: C++ Resu

51Nod1039 N^3 Mod P 数论 原根 BSGS

原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1039.html 题目传送门 - 51Nod1039 题意 题解 这题我这个做法要卡常数. 不好意思我只是来存代码的. 代码 #include <bits/stdc++.h> using namespace std; const int N=100005; int T,A,B,P; int Fac_p[N],Fac_tot,g; int prime[N],vis[N],pcnt=0; void G

bzoj 3239: Discrete Logging【BSGS】

BSGS的板子题 此时 \( 0 \leq x \leq p-1 \) 设 \( m=\left \lceil \sqrt{p} \right \rceil ,x=i*m-j \)这里-的作用是避免逆元 于是可以把式子变形成这样:\( a^{im}\equiv ba^j(mod p) \) 枚举右边\( 0 \leq j <m \) ,用map或者hash以模数为下标来存每一个j 枚举左边\( 0 \leq i <m \) ,在map或者hash中查找对应的模数 #include<ios