Root(hdu5777+扩展欧几里得+原根)
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(1≤sum≤100000000) ,we
have m queries
which contains a pair (xi,yi )
and would like to know the smallest nonnegative integer ki satisfying 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 integerssum,m(1≤sum≤100000000,1≤m≤100000) in
the first line.
The nextm lines
will contains two intgeers xi,yi(0≤xi,yi≤1000000000)
For each case, each case contains two integers
The next
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.
Each line cotain a integer which is the smallest integer for (
Sample Input
1 175 2 2 1 2 3
Sample Output
Case #1: 0 3Hint175 =52∗7 20 mod 5 = 1 23 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?
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> using namespace std; typedef long long ll; const int maxn=1e6+1; const int maxv=1e5+1; bool isnp[maxv]; int prime[maxv],pnum;//素数数组,素数个数 int cas; void get_prime()//素数打表 { pnum=0; int i,j; memset(isnp,0,sizeof(isnp)); isnp[0]=isnp[1]=true; for(i=2; i<maxv; i++) { if(!isnp[i])prime[pnum++]=i; for(j=0; j<pnum&&prime[j]*i<maxv; j++) { isnp[i*prime[j]]=true; if(i%prime[j]==0)break; } } } ll qukpow(ll k,ll base,ll p) { ll res=1; for(; k; k>>=1) { if(k&1)res=(res*base)%p; base=(base*base)%p; } return res; } ll ppow(ll a,ll b,ll mod) { ll c=1; while(b) { if(b&1) c=c*a%mod; b>>=1; a=a*a%mod; } return c; } ll fpr[maxv]; ll find_primitive_root(ll p)//求p的原根 g^(p-1) = 1 (mod p); 求g { ll cnt=0,num=p-1,res; int i; if(p==2)return 1; for(i=0; i<pnum && prime[i]*prime[i]<=num && num>1 ; i++) { if(num%prime[i]==0)// { fpr[cnt++]=prime[i]; while(num%prime[i]==0)num/=prime[i]; } } if(num>1)fpr[cnt++]=num;//fpr[]存的是p-1的因子 for(res=2; res<=p-1; res++)//暴力 { for(i=0; i<cnt; i++) if(ppow(res,p/prime[i],p)==1)break; if(i>=cnt)return res; } return -1; }; const int mod=1e6+7; struct solve { struct HashTable { int top,head[mod]; struct Node { int x,y,next; } node[mod]; void init() { top=0; memset(head,0,sizeof(head)); } void insert(ll x,ll y) { node[top].x=x; node[top].y=y; node[top].next=head[x%mod]; head[x%mod]=top++; } ll query(ll x) { for(int tx=head[x%mod]; tx; tx=node[tx].next) if(node[tx].x==x)return node[tx].y; return -1; } } mp; ll p; ll discretelog(ll prt,ll a) //取对数 { ll res,am=ppow(prt,maxn-1,p),inv=ppow(a,p-2,p),x=1; for(ll i=maxn-1;; i+=(maxn-1)) { if((res=mp.query((x=x*am%p)*inv%p))!=-1) { return i-res; } if(i>p)break; } return -1; } void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)//扩展欧几里得 x为最后须要的k { if(!b) { d=a; x=1; y=0; } else { ex_gcd(b,a%b,d,y,x); y-=x*(a/b); } } ll proot; void init() { mp.init(); ll tmp,x,y,d; int i; proot=find_primitive_root(p);//找到素数p的原根 for(i=0,tmp=1; i<maxn-1; i++,tmp=tmp*proot%p) mp.insert(tmp%p,i*1ll); } ll query(ll x,ll y) { ll d; x%=p; y%=p; if(y==1)return 0; else if(x==0) { if(y==0)return 1; else return -1; } else if(y==0)return -1; else { ll s=discretelog(proot,x); ll t=discretelog(proot,y); ex_gcd(s,p-1,d,x,y); if(t%d)return -1; else { ll dx=(p-1)/d; x=(x%dx+dx)%dx; x*=(t/d); x=(x%dx+dx)%dx; return x; } } } } sol[32]; int main() { int i,j,q,con,T; ll sum,x,y; scanf("%d",&T); get_prime(); cas=1; while(cas<=T) { con=0; scanf("%I64d %d",&sum,&q); for(i=0; i<pnum&&prime[i]*prime[i]<=sum&&sum!=1; i++) { if(sum%prime[i]==0)//素数存起来 { sol[con].p=prime[i]; sol[con].init(); con++; while(sum%prime[i]==0)sum/=prime[i]; } } if(sum>1) { sol[con].p=sum; sol[con].init(); con++; } printf("Case #%d:\n",cas++); for(i=0; i<q; i++) { scanf("%lld %lld",&x,&y); ll res=1e18,tmp; for(j=0; j<con; j++) { tmp=sol[j].query(x,y); if(tmp!=-1)res=min(res,tmp); } if(res==1e18)res=-1; printf("%I64d\n",res); } } return 0; }