Root(hdu5777+扩展欧几里得+原根)2015 Multi-University Training Contest 7

Root

Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 34    Accepted Submission(s): 6


Problem Description
Given a number sum(1sum100000000),we have m queries which contains a pair (xi,yi) and would like to know the smallest nonnegative integer kisatisfying xkii=yi mod p when the prime number p (sum mod p=0)(ps:00=1)
 
Input
The first line contains a number T, indicating the number of test cases. 

For each case, each case contains two integers sum,m(1sum100000000,1m100000) in the first line. 

The next m lines will contains two intgeers xi,yi(0xi,yi1000000000)
 
Output
For each test case,output "Case #X:" and m lines.(X is the case number) 

Each line cotain a integer which is the smallest integer for (xi,yi) ,if we can't find such a integer just output "-1" without quote.
 
Sample Input
1
175 2
2 1
2 3
 
Sample Output
Case #1:
0
3
Hint
 
175 =5^27
2^0 mod 5 = 1
2^3 mod 7 = 1
So the answer to (2,1) is 0
 
Source
 
 
 
比较经典一道扩展欧几里得 



现在,我们首先来解决下原根的问题:简单的解释可以参考:>>原根<<  

 资源下载:http://download.csdn.net/detail/u010579068/8993383

不急看懂的,可以先去切道 定义题    链接:1135 原根  

解题 http://www.cnblogs.com/yuyixingkong/p/4722821.html

转载请注明出处:寻找&星空の孩子     

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5377

 
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<map>
  7 using namespace std;
  8 typedef long long ll;
  9 const int maxn=1e6+1;
 10 const int maxv=1e5+1;
 11 bool isnp[maxv];
 12 int prime[maxv],pnum;//素数数组,素数个数
 13 int cas;
 14 void get_prime()//素数打表
 15 {
 16     pnum=0;
 17     int i,j;
 18     memset(isnp,0,sizeof(isnp));
 19     isnp[0]=isnp[1]=true;
 20     for(i=2; i<maxv; i++)
 21     {
 22         if(!isnp[i])prime[pnum++]=i;
 23         for(j=0; j<pnum&&prime[j]*i<maxv; j++)
 24         {
 25             isnp[i*prime[j]]=true;
 26             if(i%prime[j]==0)break;
 27         }
 28     }
 29 }
 30 ll qukpow(ll k,ll base,ll p)
 31 {
 32     ll res=1;
 33     for(; k; k>>=1)
 34     {
 35         if(k&1)res=(res*base)%p;
 36         base=(base*base)%p;
 37     }
 38     return res;
 39 }
 40 ll ppow(ll a,ll b,ll mod)
 41 {
 42     ll c=1;
 43     while(b)
 44     {
 45         if(b&1) c=c*a%mod;
 46         b>>=1;
 47         a=a*a%mod;
 48     }
 49     return c;
 50 }
 51 ll fpr[maxv];
 52 
 53 ll find_primitive_root(ll p)//求p的原根    g^(p-1) = 1 (mod p); 求g
 54 {
 55     ll cnt=0,num=p-1,res;
 56     int i;
 57     if(p==2)return 1;
 58     for(i=0; i<pnum && prime[i]*prime[i]<=num && num>1 ; i++)
 59     {
 60         if(num%prime[i]==0)//
 61         {
 62             fpr[cnt++]=prime[i];
 63             while(num%prime[i]==0)num/=prime[i];
 64         }
 65     }
 66     if(num>1)fpr[cnt++]=num;//fpr[]存的是p-1的因子
 67     for(res=2; res<=p-1; res++)//暴力
 68     {
 69         for(i=0; i<cnt; i++)
 70             if(ppow(res,p/prime[i],p)==1)break;
 71         if(i>=cnt)return res;
 72     }
 73     return -1;
 74 };
 75 
 76 const int mod=1e6+7;
 77 
 78 struct solve
 79 {
 80     struct HashTable
 81     {
 82         int top,head[mod];
 83         struct Node
 84         {
 85             int x,y,next;
 86         } node[mod];
 87         void init()
 88         {
 89             top=0;
 90             memset(head,0,sizeof(head));
 91         }
 92         void insert(ll x,ll y)
 93         {
 94             node[top].x=x;
 95             node[top].y=y;
 96             node[top].next=head[x%mod];
 97             head[x%mod]=top++;
 98         }
 99         ll query(ll x)
100         {
101             for(int tx=head[x%mod]; tx; tx=node[tx].next)
102                 if(node[tx].x==x)return node[tx].y;
103             return -1;
104         }
105     } mp;
106 
107     ll p;
108     ll discretelog(ll prt,ll a) //取对数
109     {
110         ll res,am=ppow(prt,maxn-1,p),inv=ppow(a,p-2,p),x=1;
111         for(ll i=maxn-1;; i+=(maxn-1))
112         {
113             if((res=mp.query((x=x*am%p)*inv%p))!=-1)
114             {
115                 
116                 return i-res;
117             }
118             if(i>p)break;
119         }
120         return -1;
121     }
122     void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)//扩展欧几里得 x为最后需要的k
123     {
124         if(!b)
125         {
126             d=a;
127             x=1;
128             y=0;
129         }
130         else
131         {
132             ex_gcd(b,a%b,d,y,x);
133             y-=x*(a/b);
134         }
135     }
136 
137     ll proot;
138     void init()
139     {
140         mp.init();
141         ll tmp,x,y,d;
142         int i;
143         proot=find_primitive_root(p);//找到素数p的原根
144         for(i=0,tmp=1; i<maxn-1; i++,tmp=tmp*proot%p)
145             mp.insert(tmp%p,i*1ll);
146     }
147     ll query(ll x,ll y)
148     {
149         ll d;
150         x%=p;
151         y%=p;
152         
153         if(y==1)return 0;
154         else if(x==0)
155         {
156             if(y==0)return 1;
157             else return -1;
158         }
159         else if(y==0)return -1;
160         else
161         {
162             ll s=discretelog(proot,x);
163             
164             ll t=discretelog(proot,y);
165             
166             ex_gcd(s,p-1,d,x,y);
167             if(t%d)return -1;
168             else
169             {
170                 ll dx=(p-1)/d;
171                 x=(x%dx+dx)%dx;
172                 x*=(t/d);
173                 x=(x%dx+dx)%dx;
174                 return x;
175             }
176         }
177     }
178 } sol[32];
179 int main()
180 {
181     int i,j,q,con,T;
182     ll sum,x,y;
183     scanf("%d",&T);
184     get_prime();
185     cas=1;
186     while(cas<=T)
187     {
188         con=0;
189         scanf("%I64d %d",&sum,&q);
190 
191         for(i=0; i<pnum&&prime[i]*prime[i]<=sum&&sum!=1; i++)
192         {
193             if(sum%prime[i]==0)//素数存起来
194             {
195                 sol[con].p=prime[i];
196                 sol[con].init();
197                 con++;
198                 while(sum%prime[i]==0)sum/=prime[i];
199             }
200         }
201         if(sum>1)
202         {
203             sol[con].p=sum;
204             sol[con].init();
205             con++;
206         }
207 
208         printf("Case #%d:
",cas++);
209 
210         for(i=0; i<q; i++)
211         {
212             scanf("%lld %lld",&x,&y);
213 
214             ll res=1e18,tmp;
215             for(j=0; j<con; j++)
216             {
217  
218                 tmp=sol[j].query(x,y);
219                 if(tmp!=-1)res=min(res,tmp);
220             }
221             if(res==1e18)res=-1;
222             printf("%I64d
",res);
223         }
224     }
225     return 0;
226 }
 
原文地址:https://www.cnblogs.com/yuyixingkong/p/4722835.html