HDU5478 原根求解

看别人做的很简单我也不知道是怎么写出来的

自己拿到这道题的想法就是模为素数,那必然有原根r ,将a看做r^a , b看做r^b
那么只要求出幂a,b就能得到所求值a,b

自己慢慢化简就会发现可以抵消n
然后扩展欧几里得解决,一个个枚举所有模的情况。。。。

中间利用了欧拉准则可以知道 对所有奇素数而言: a^((p-1)/2) = -1(mod p)

利用上述准则,这样就不用baby_step giant_step的办法了

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4
  5 const int N = 200010;
  6
  7 LL P , k1,b1 , k2;
  8 bitset<N> prime;
  9 int p[N],pri[N];
 10 int k,cnt;
 11
 12 void isprime()
 13 {
 14     prime.set();
 15     for(int i=2; i<N; i++)
 16     {
 17         if(prime[i])
 18         {
 19             p[k++] = i;
 20             for(int j=i+i; j<N; j+=i)
 21                 prime[j] = false;
 22         }
 23     }
 24 }
 25
 26 void Divide(int n)
 27 {
 28     cnt = 0;
 29     int t = (int)sqrt(1.0*n+0.5);
 30     for(int i=0; p[i]<=t; i++)
 31     {
 32         if(n%p[i]==0)
 33         {
 34             pri[cnt++] = p[i];
 35             while(n%p[i]==0) n /= p[i];
 36         }
 37     }
 38     if(n > 1)
 39         pri[cnt++] = n;
 40 }
 41
 42 void gcd(LL a , LL b , LL &d , LL &x , LL &y)
 43 {
 44     if(!b){d=a;x=1;y=0;}
 45     else{gcd(b,a%b,d,y,x);y-=x*(a/b);}
 46 }
 47
 48 LL inv(LL a , LL n)
 49 {
 50     LL d,x,y;
 51     gcd(a,n,d,x,y);
 52     return d==1?(x+n)%n:-1;
 53 }
 54
 55 LL quick_mod(LL a,LL b,LL m)
 56 {
 57     LL ans = 1;
 58     a %= m;
 59     while(b)
 60     {
 61         if(b&1)
 62         {
 63             ans = ans * a % m;
 64             b--;
 65         }
 66         b >>= 1;
 67         a = a * a % m;
 68     }
 69     return ans;
 70 }
 71
 72 LL pow_mod(LL a , LL p , LL n)
 73 {
 74     LL ret= 1;
 75     while(p){
 76         if(p&1) ret = ret*a%n;
 77         a = a*a%n;
 78         p>>=1;
 79     }
 80     return ret;
 81 }
 82
 83 LL mul_mod(LL a , LL b , int n)
 84 {
 85     return a*b%n;
 86 }
 87
 88 //int log_mod(int a , int b , int n)
 89 //{
 90 //    int m , v , e=1 , i;
 91 //    m = (int)sqrt(n+0.5);
 92 //    v = inv(pow_mod(a,m,n) , n);
 93 //    map<int,int>x;
 94 //    x.clear();
 95 //    x[1] = 0;
 96 //    for(i=1 ; i<m ; i++){
 97 //        e = mul_mod(e , a , n);
 98 //        if(!x.count(e)) x[e]=i;
 99 //    }
100 //    for(i=0 ; i<m ; i++){
101 //        if(x.count(b)) return i*m+x[b];
102 //        b = mul_mod(b,v,n);
103 //    }
104 //    return -1;
105 //}
106
107 #define pii pair<int,int>
108 pii ans[N];
109
110 int main()
111 {
112    // freopen("a.in" , "r" , stdin);
113     int cas = 0;
114     isprime();
115     //>>k1>>b1>>k2
116     while(cin>>P>>k1>>b1>>k2)
117     {
118         printf("Case #%d:\n" , ++cas);
119         int tot = 0;
120         /*P==2另外处理*/
121         if(P==1){
122             printf("%d %d\n" , 0,0);
123             continue;
124         }
125         if(P==2){
126             printf("%d %d\n" , 1,1);
127             continue;
128         }
129         Divide(P-1);
130
131         for(int g=2; g<P; g++)
132         {
133             bool flag = true;
134             for(int i=0; i<cnt; i++)
135             {
136                 int t = (P - 1) / pri[i];
137                 if(quick_mod(g,t,P) == 1)
138                 {
139                     flag = false;
140                     break;
141                 }
142             }
143             if(flag)
144             {
145                 LL root = g;
146                 LL val = (P-1)/2;
147                // cout<<root<<" "<<val<<endl;
148                 LL d,x,y;
149                 gcd(b1+k1 , -1 , d , x , y);
150                 x = x*val , y = y*val;
151
152                 x = ((x%(P-1))+(P-1))%(P-1);
153                 y = ((y%(P-1))+(P-1))%(P-1);
154                 for(int i=0 ; i<P-1 ; i++){
155
156                     if((x*k1-y*k2)%(P-1)==0){
157                             LL a = pow_mod(root , x , P);
158                         LL b = pow_mod(root , y , P);
159                         if(a>0&&b>0) ans[tot++] = make_pair((int)a , (int)b);
160                     }
161                     x = (x+1)%(P-1);
162                     y = (y+b1+k1)%(P-1);
163                 }
164                 break;
165             }
166         }
167         sort(ans , ans+tot);
168         tot = unique(ans , ans+tot)-ans;
169         if(tot==0) puts("-1");
170         else{
171             for(int i=0 ; i<tot ; i++) printf("%d %d\n" , ans[i].first , ans[i].second);
172         }
173     }
174     return 0;
175 }
时间: 2024-10-13 12:01:13

HDU5478 原根求解的相关文章

codeforces#536题解

CodeForces#536 A. Lunar New Year and Cross Counting Description: Lunar New Year is approaching, and you bought a matrix with lots of "crosses". This matrix \(M\) of size \(n \times n\) contains only 'X' and '.' (without quotes). The element in t

x^a=b(mod c)求解x在[0,c-1]上解的个数模板+原根求法

/************************************* 求解x^a=b(mod c) x在[0,c-1]上解的个数模板 输入:1e9>=a,b>=1,1e9>=c>=3. 返回:调用xaeqbmodc(a,b,c),返回解的个数 复杂度: 找原根的复杂度很低,所以总的复杂度为O(c^0.5) ************************************/ typedef long long ll; #define HASH_N 100007 str

【bzoj2219-数论之神】求解x^a==b(%n)-crt推论-原根-指标-BSGS

http://www.lydsy.com/JudgeOnline/problem.php?id=2219 弄了一个晚上加一个午休再加下午一个钟..终于ac..TAT 数论渣渣求轻虐!! 题意:求解 x^A=B(mod n) 在0~n内解的个数.其中1 <= A, B <= 10^9, 1 <= K <= 5 * 10^8  (n=2*K+1) 首先先说这一题的弱化版:bzoj1319 http://www.lydsy.com/JudgeOnline/problem.php?id=1

51Nod 1135-原根(快速求解一个素数的原根)

题目地址:51Nod 1135 1.原根定义:设m>1,gcd(a,m)=1,使得成立的最小的r,称为a对模m的阶. 2.定理:如果模m有原根,那么他一共有个原根. 3.定理:如果p为素数,那么素数p一定存在原根,并且模p的原根的个数为个. 4.定理:假设m是正整数,a是整数,如果a模m的阶等于,则称a为模m的一个原根. 5.模m有原根的充要条件:m=2,4,P^a,2*P^a--. 求模素数P的原根的方法:对P-1素因子分解,即P-1=(P1^a1)(P2^a2)-..(Pk^ak).,若恒有

[学习笔记]原根

欧拉定理 若$a,p\;\in\;N^{+},(a,p)=1$,则$a^\phi(p)\;\equiv\;1(mod\;p)$. 阶 使得$a^x\;\equiv\;1(mod\;p)$的最小正整数$x$称为$a$模$p$的阶,记为$ord_pa$. 实现 找一个数的阶可以暴力求解,原根为$\phi(p)$的因数. 例题 yayamao的神题. 原根 原根:$ord_pa=\phi(p)$时,称$a$是$p$的原根. $a^1,a^2,...,a^{\phi(p)}$在模p意义下互不相同. 如果

51nod1135(求最小原根)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1135 题意:中文题诶- 思路:设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根.(其中φ(m)表示m的欧拉函数)给出1个质数P,找出P最小的原根. 我们先了解一下阶的概念:满足 a^r Ξ (1 mod m) ---1 的最小 r 即为 a%m的阶,我们可以直接从小到大枚举a, 然后将 r= φ(m) 带入进去, 判断如果满足  1式

【转载】学习总结:初等数论(3)——原根、指标及其应用

写得太好了..忍不住转载啊.. 未授权,侵权删. 原博文链接:http://blog.163.com/[email protected]/blog/static/172279052201641935828402/ --------------------------------------------------------------------------------- 学习总结:初等数论(3)——原根.指标及其应用 最近知道了一本书叫<数论概论(第3版)>(A Friendly Intr

【转】初等数论 ——原根、指标及其应用

转自:http://blog.163.com/[email protected]/blog/static/172279052201641935828402/ 学习总结:初等数论(3)——原根.指标及其应用 2016-05-19 15:58:28|  分类: 信息学——学习总 |  标签:初等数论  数学  |举报|字号 订阅 学习总结:初等数论(3)——原根.指标及其应用 最近知道了一本书叫<数论概论(第3版)>(A Friendly Introduction to Number Theory

poj 1284 Primitive Roots 【原根】【数论】

题目链接 :传送门 题目大意: 求一个质数的原根个数. 先普及一下原根的定义: 设m是正整数,a是整数,若a模m的阶等于euler(m),则称a为模m的一个原根. eg: m=7,euler(7) =  6(1,2,3,4,5,6) 则: 1   1^(n)mod7=1! = 6 2   2^(n)mod7={2 4 1}!=6 3   3^(n)mod7={3,2,6,4,5,1}==6   故3是模7的原根 4   4^(n)mod7={4,2,1}!=6 5   5^(n)mod7={5,